So I have received a lot of email and even a couple of phone calls regarding yesterday's article by Mediaplex's Sean Quick in iMediaConnection. How could I let an article on Gaining Ground with Behavioral Targeting go by without so much as a comment, when so much of my blog addresses this topic with such conviction? Well, yesterday was my birthday so I was out having a much needed break! But I'll have at it now!
Okay, first of all I have to start off by saying that Sean did a good job of breaking up BT into two distinct categories – passive and active. He used these descriptions to help us understand the difference between the classic event-based targeting capabilities of a TACODA and the re-targeting capabilities that I have been evangelizing on this blog. I was so pleased to see Sean use the term customer re-targeting as well, since it was not an industry term when I first started this blog and my Urchin reports show Mediaplex on my blog everyday. I take Sean's usage of the term as a compliment J.
Anyway, back to Sean's article. While Sean does specifically highlight ValueClick's Mediaplex as the provider of re-targeting, he also mentioned DoubleClick and Advertising.com. So I don't fault him for direct self-promotion. But what I do believe Sean fails to do is accurately depicting customer re-targeting as it has come to be defined.
If anything I believe that what Sean has done is introduced a third form of behavioral targeting: (1) passive, (2) active event-based and (3) active segment-based.
Passive BT — also sometimes called Targeted Segments and other names — is generally done either through applications that reside on a user's computer, such as downloaded software, or through tracking tags that reside on publishers' websites. In either case, these technologies anonymously record consumer web browsing activity. The consumer is unaware that such tracking is occurring, as it doesn't affect their surfing activity in any noticeable way.
The tracking information is collected and analyzed, and the cornerstone of this approach is the subsequent attempt to make increasingly educated guesses about a consumer's interests based on the data in order to deliver timely and relevant marketing communications.
Examples of providers of this approach include Tacoda, Revenue Science and Claria.
So this is still event-based. A better description is Event-Based Active BT. The information leveraged for re-targeting is based on other marketing experiences. Sean does not describe the application of this BT specifically in terms of online advertising, nor does he describe it in terms of preventing the re-prospecting of customers through online advertising. In fact, what he is doing is explaining that Event-Based Active BT can coordinate disparate forms of online marketing to collectively create a concrete BT model. Moreover, and what is entirely left out of this article is the PROCESS.
One thing that I am so careful to do in all of my postings – and what I believe will be a focus of articles that I would write for IMC – is to illuminate the procedural differences between various kinds of technologies so that people can come to distinguish them. It is important to understand the impact of a first party design and a third party design for example. The benefits and differences of these kinds of technologies transcend the advertising experience for both the advertiser and user – in fact for the publisher too.
TruEffect holds the patent-pending rights to first party ad serving. So if another ad server were to implement a first party design, they would violate that patent and would be putting their clients in a nefarious situation that would result in problems down the road. Aside from that, other ad servers are not doing it that way anyway right now. They have their own design using a third party cookie and a synchronization process. They still have their 'control the data and you own the client' model.
Listen, Sean is not going to talk to me about it, obviously. But maybe he will talk to you and then you can come back and talk to all of us on the blog. OR, maybe Sean would like to come on here and have a discussion with all of us. It would be great to bring the truth out.
If Mediaplex is using a third party cookie to conduct user re-targeting, it is historically synchronizing. Latency comes into play and there are limitations to the benefits that only a real-time capability can bring to the table. Only a first party cookie foundation is capable of doing it in real-time.
Mediaplex can not adjust targeting strategies in real-time, targets must be determined in advanced.
As we have covered in many entries on this blog. First party ad serving, using a first party cookie, allows all of the four aforementioned limitations to be mitigated. Most of all, targeting can happen in real-time. An advertiser can change a cookie value, login to the ad server and change the targeting reaction to the cookie; and the change is instantaneous.
With a third-party implementation, the advertiser has have to share the altered customer information with the ad server (Mediaplex, DoubleClick) and then the ad server has to start writing new cookies, which have to propagate, and then the ad targeting can begin. Can you say latency?
Two other limitation issues: (1) SOX and (2) third party cookie deletion.
When a third party is handling your data, and you have SOX compliance issues, you have a potential problem. Using a third-party cookie and a third party ad server, deploying event-based Active BT, means your data about your customers is being shared with a third party who is subsequently developing additional information about your customers and gate-keeping your access to that data. You need to make sure that you have controls written about the handling of that data because it is out of your control. This is not an issue with first party ad serving because all of your ad serving data flows directly through to the advertiser and is not withheld by the ad server.
Secondly, third party cookies get deleted over 40% of the time – Jupiter Research. So only 60% of the Event-Based Active BT will be effective whereas over 90% of first party cookies are persistent. Do the math and you will realize that leveraging a first party cookie will bring a much higher yield in re-targeting activities.
So Sean's article stimulates the interest and probably results in some genuine leads to Mediaplex, but I wonder how far down the path you will get with Mediaplex before you come to realize that you have not come to engage with customer re-targeting but more event-based BT?
The third form of BT that I characterized earlier is Active Customer Re-targeting. The fundamental distinguishing difference is that the advertiser is creating customer segments and is cookieing their customers directly, as opposed to the ad server cooking the customer. Advertisers may cookie their customers through eCRM, eCommerce cycles, email processes, site-side analytic platforms (i.e., WebSideStory), landing pages (i.e., CoreMetrics) all using their own first party cookie. They can create customer segment profiles that associate a user with a customer type, just like they do offline with direct mail, cataloging and telemarketing and then deploy customer re-targeting with their online advertising.
So Sean, it would be very interesting to have a follow-up article with which we hear how Mediaplex, and if you're so inclined to research your other examples – Advertising.com and DoubleClick – conduct the Event-Based Active User Re-targeting. But that might not be on your agenda. Hey Brad, maybe I'll write that article for you!


text:
Tattoo Search
Tattoo Talk
Apprenticeships & Advice
Tattoo Artists Forum
Jobs and Placements
Laser Removal
Reader Interviews
Studio Profiles
Public Animal No.9 - PETA's "Ink Not Mink"
Published: 04 April, 2011 - Featured in Skin Deep 197, April, 2011
I had heard of PETA and their various print and public campaigns for years but it was only in 2009 when I read Dan's memoir, "Committed", that I learned about the man himself and what drove him to dedicate his life to this particular cause.
Thanks to its crazy and often brutally honest animal rights campaigns, PETA (People for the Ethical Treatment of Animals) is now a global household name. Stunts such as storming the environmental Earth Summit dressed as cows and blood stained butchers or taking over the offices of Calvin Klein's head offices in New York to protest against Klein's use of fur, PETA has established itself as a maverick force to be reckoned with. But behind the daredevil campaigns, is a quiet and unassuming man that most people will not have heard of – Vice President, Dan Mathews.
As Dan puts it himself, he started out life as a 'meat enthusiast'. Such was his love of all things meaty, his father who owned a diner, even named a meat dish after him - the 'Danny Dog'. But it was two separate events that occurred when Dan was around fourteen that would change his views forever. "Although I grew up a fairly gleeful misfit, I was often dragged into traumatizing fights for being gay. One morning, I was rushing down the hallway between classes and some one yelled, 'Faggot!' and slugged me in the gut, sending me tumbling over with the wind knocked out of me. Stunned, I looked up to see a collection of chuckling faces as I lay there gasping for breath."
This was the first event that would change his life, the second happened a few weeks later when Dan found himself on a fishing trip with his father. Dan was fishing when he felt a bite on his line. He reeled in his catch and when it was on the boat, another guy on the trip proceeded to tear the hook out of the fish's mouth, causing blood to start pumping out everywhere. "Everybody was laughing but all I could think of was what the scene looked like from the flounder's point of view. Stunned, the fish was looking up to see a collection of chuckling faces as he lay gasping for breath. In that instant, the flounder was the only creature on the boat I could relate to. I felt sick. I had become one of the terrorizing bullies I dreaded so much at school. Most people are sensitized to the plight of animals by cute, cuddly, four-legged balls of fur, whereas I sympathised with a rubbery bottom-feeder. I never ate fish again and gradually stopped eating anything with eyes, except for potatoes."
Two separate events but one life changing shift and the birth of an animal rights activist. But it wasn't so easy in the beginning, as Dan puts it, "I eagerly shared my new ideas of what it meant to be civilised with anyone who would listen – and plenty who wouldn't. I was naively confident that everybody would grasp this simple, noble logic and adopt the same basic regard for fish and chickens as they had for dogs, cats and all the other animals with a heart, brain and nervous system. I might as well have been advocating rights for pet rocks."
It was seven years later, that Dan would find himself working as a receptionist for a young organization called PETA and it was here that things really took a turn. Within a week Dan found himself and a hundred other protestors, taking over the grants office at the National Institutes of Health. From that first campaign, Dan was hooked. "I began the week as a receptionist and finished it feeling like a real revolutionary!"
So why did PETA turn into such an 'in your face' kind of organization? Why not carry on as other animal rights protestors had done before in the past?
"For many years I had pushed campaigns that appealed to people's intellect and compassion but as cable TV and the internet began to mould a society more interested in entertainment than education, serious topics began to take a back seat to scandal and sensation. So we had to dream up flashier ways to compete for people's attention. Of course, in doing so we often have had to make ourselves look quite silly which is fine by me because at heart I am a very silly person."
And that was how PETA and Dan Mathews lives' became entwined in one madcap campaign after another. One of the latest campaigns to hit the public squarely between the eyes, is their Ink Not Mink poster campaign. For this brilliant anti-fur campaign, PETA has sought out the most inked celebrities to get their kit off with the aim to bring an end to the fur trade. But before we moved on to the campaign, Dan sent me off to look at some of the online resources that PETA has gathered about the world fur trade. At this point, I never realised what I was in for.
"Fur farming is about one of the worst fates that can happen to an animal. As an industry it didn't develop until the late 1800s, when fashion demands put market demands ahead of huntable supplies. The majority of the world's fur farms are located in Northern Europe, with about 10% located in the United States. In pursuit of the perfect pelt, animals are bred and raised just to be killed for their skins. They are kept in crowded, minimally-sized cages or pens and then killed as soon as they develop the desired quality of coat. Anywhere from 10%-25% of the animals die from poor conditions or disease before they can be 'harvested'."
Sounds terrible but it gets worse, much worse. The most farmed animal is mink, followed by chinchillas and foxes. These animals are killed via just about any means possible, provided that the death does not damage the animals fur. Electrocution and drowning are frequently used options as both these methods leave the fur undamaged. Sadly, watching the Ink Not Mink videos online, I was quick to learn, that these two options pale into insignificance when you realise that a significant percentage of animals survive this 'euthanasia' and are then skinned while still alive.
So now, with a head full of images I wish I never had, I return to Dan and the Ink Not Mink campaign to find out more about how it all started. "I came up with the idea for the campaign after meeting Dennis Rodman at an MTV party in Miami. I had seen him in fur before and when we met I asked how such a cool guy could be a fur pimp. He told me the few times he'd worn it, it was fake, and that he loved animals and PETA's style. So I asked him to be the first guy in our naked campaign. It was only when I saw his tattoos and amazing body I suggested he pose like Rodin's famous "Thinker" statue and came up with the tagline "Think Ink Not Mink." We met up in an LA studio a few weeks later and shot it, then Rodman came to NY to unveil it during Fashion Week and it became one of the most viewed photos on the web that week and an all round media sensation. After that response we decided to make it a series but without repeating the Rodin statue theme."
Looking through the posters, I ask Dan why there is a lack of tattooed ladies represented and in true Dan style, though serious, the answer is laced with his quirky sense of humour. "We ended up doing mostly men for this because we already shot so many women for the
'I'd Rather Go Naked Than Wear Fur' campaign. We like to be equal opportunity nudists."
Indeed, it is important to make sure that we all have a fair crack at being naked for the causes we believe in. Since the original Dennis Rodman shoot in 2005, many famous male personalities have stripped off to reveal their tattoos for the campaign. With actors, sport stars and tattooists amongst those on the list, no industry has been left uncovered. If you have tattoos and are famous, PETA will be onto you soon enough. As Dan says, "We recruit based on who we hear about with tattoos."
So has there been any that have got away from Dan's clutches? "The one that got away is Amy Winehouse. We had a night on the town in Vegas last year and she told us she doesn't wear fur and that she loved the campaign slogan. But we haven't managed to pin her down for a shoot yet!" The way Dan works though, I am sure that missed opportunity will be rectified soon enough.
I ask Dan if he has any tattoos. I mean, being around all these tattoo covered people must have given an itching for a little ink himself. "I have a 777 tattoo on my arm. Like the sevens you get on the slot machines. It was in Las Vegas after a lucky pull on a slot machine. I had long wanted a tattoo but didn't want anything I'd seen before and I liked the idea of having a good luck logo emblazoned on my arm. My mom says it counteracts the 666 I was born with on my skull."
The sign of the devil or Lucky 7's, whichever drives Dan to do what he does, it makes no difference in the long run. What is important, is the work PETA does and without Dan and his magic touch and crazy imagination, I don't think PETA would be as effective in changing people's perceptions as it has been.
"Being a nonconformist, I never imagined that I would have the same job for decades. A job that has entailed being carried off by police in my underwear at a fur expo in Hong Kong, impersonating a priest to crash a fashion show in Milan and donning a cow costume to storm a cattleman's convention in Denver. I've conducted business meetings in settings ranging from a skinny-dipping party at the Playboy mansion to the office of the archbishop of Turin to an ornate box overlooking the Vienna Opera Ball. I've picked up the phone to get an angry earful from Madonna when I spoke out against her bullfighting-themed music videos. I've also picked up the phone to hear Sir Paul McCartney insisting we take the rest of the day off when he'd successfully pressured McDonald's to stop buying meat from slaughterhouses that fail USDA inspection. It doesn't matter that some people think we're crazy. Most kids whose sense of justice has yet to be corrupted absorb the message. This has made animal rights a top concern for today's youngsters."
So even after being arrested, receiving death threats and once very nearly ended up being committed after a demonstration in Paris, I have a feeling that Dan is not ready to give up on animal rights just yet. Even more so, when campaigns like Ink Not Mink push PETA and their message, from strength to strength. And whatever is turning around in his head, slowly forming itself into a new approach to this important issue, you can bet, as serious as the subject matter will be - it is going to be one hell of a lot of fun!
Dennis Rodman is where it all began on the Ink Not Mink campaign trail. Known for causing as big a controversy off the basketball court for his wardrobe, as he is on the court for his rebounding, Dennis Rodman was the perfect place to kick off PETA's anti-fur campaign. Rodman played alongside Michael Jordan on three championship Chicago Bulls teams in the nineties. Yet he was better known for his eccentric and attention-hunting behaviour, especially his habit of changing hair colours weekly or daily and these same traits made him a media magnet.
On watching Pamela Anderson's PETA video, showing how animals live and die before being made into fur coats and collars, Rodman said, "If you actually look at the video firsthand, it gives you a different perspective on animals and how they're treated. It's heart-wrenching to see what they go through! You get this sense of urgency that you have to help these animals out. I watched it and thought, that is a hard way to die! And it's not right to kill animals for our pleasure."
Inspired by hearing a Hendrix song in a skate park when he was a kid, Dave Navarro, picked up a six string and in 1986, joined Jane's Addiction as their guitarist. The band were successful around the world but ended up splitting up in 1991 due to personal tensions. On the back of NME's 'Godlike Genius Award for Services to Music', Jane's Addiction reunited again in 2008. The reunion and subsequent performance led to the band being contacted by Trent Reznor to collaborate. A double headlining tour by the band followed in 2009, cleverly branded the NIN/JA tour by fans.
A reformed fur-wearer, Navarro has sworn off fur since learning where it comes from, "There was a time in my life when I used to wear over the top outfits and some of those outfits contained fur. I was uneducated as to where it came from, I just thought it looked good. Several years ago I saw video footage of animals being skinned alive and screaming, and it honestly is the most horrific, inhumane thing I've ever seen. It's simple, just stay away from fur!"
Born in Athens, Greece, Lee's family moved to California when he was only a year old. By the age of four, he had his first drum kit but he still had to wait awhile before he got his hands on some proper skins. It was during the late seventies while playing the Sunset Strip, with his current band Suite 19, that he met Nikki Sixx - not long after this initial meeting, Mick Mars and Vince Neil joined the band and Mötley Crüe was born.
Tommy Lee first learned about PETA through long time animal advocate, and ex-wife, Pamela Anderson. Says Lee in an interview with PETA, "I have actually been looking forward to getting involved. I get the PETA magazine and what the fur trade does to animals is absolutely terrifying. … A lot of hip-hop artists wear fur, and they think it's a status symbol. That doesn't register for me, I just see
dead animals."
Growing up in Austria, where tattooing was not just frowned upon but completely illegal, he came up through the underground. Now, with a celebrity clientele including Lenny Kravitz, Sylvester Stallone, Tommy Lee and Usher to name a few, Mario owns five tattoo studios including Mario Barth's Starlight Tattoo at the Mandalay Bay Hotel and Casino in Las Vegas as well as his latest venture, King Ink at the Mirage.
"When someone wears fur, I'm gonna try and find out if that person knows how the animal got killed. Do you know they stick an electrical probe up the animals ass so they don't damage the fur, so that you can look good? Animals are living beings with their own thought processes and feelings. They experience pain just like us."
Ami James
Ami James' face is known the world over for the hit series, Miami Ink. James is the co-owner of the tattoo studio, Love Hate Tattoos (Miami Ink is the name of the show, not the shop) in Miami Beach, Florida where he is also the co-owner of the clothing company DeVille with Chris Nunez and Jesse Fleetand has an investment in Love Hate Choppers Jewellery, with Boston jeweller Larry Weymouth.
His feelings about the fur industry are so strong that Ami flatly refused to create a design for Roberto Cavalli Vodka after finding out that Cavalli uses fur in his lines. And his commitment to animals tortured and skinned for their fur doesn't stop there—Ami has implemented Miami's first-ever fur-free policy at his bar, Love Hate. "I think it is really up to the youth to make a change. The younger generation really need to get interested in how to make this planet a better place, how to treat animals better, how not to wear fur and mink!"
Carey Hart
Carey Hart is one of the most recognized names in all of freestyle motocross. In 1998, the freestyle motocross movement was born with Hart leading the way. Hart etched his name in the record books as the first rider ever to complete a back flip on a 250cc motorcycle. In 2004 Hart's passion for tattoos turned into a business venture. Hart & Huntington Tattoo Company opened their doors in the Palms Casino, Las Vegas. This move lead to another TV opportunity for Hart when the A&E network decided to follow him and the workings of the shop in their own reality show: INKED.
He credits his wife, Pink, with educating him about animal rights. "My wife is very big into PETA and being involved with her over the years, she raised my awareness. And I'm big into how animals are treated, so anything I can do on my part to help I do. It's just ridiculous—you know, it's like you're gonna destroy animals so that you can look cool in a nightclub or you can look cool walking down the street in New York. I don't get behind that. I think it's very petty and very shallow."
Text: Trent Aitken-Smith; Photography: PETA & As Credited
Article Images
Magazines:
Skin Deep 197
Chris Nunez - Miami Ink
Kat Von from Miami Ink
Starlight Tattoo Las Vegas
King Ink Tattoo & Body Piercing
Love Hate Tattoo
Hart & Huntington Las Vegas
Skin Deep 197 On Sale: 4 April 2011 Issue: 197
RRP : £3.95
What else is in Skin Deep 197?
Wicked Game - Carl Löfqvist
In At the Deep End - 197
Smallman Syndrome - 197
Tattoo Vixens - Virginia Humann
Tattoo Vixens - Nikki Napalm
Tattoo Vixens - Amy
Tattoo Vixens - Leah Debrincat
Tattoo Vixens - Aima Indigo
Tattoo Vixens - Melissa
Tattoo Vixens - Rockwell deVil
Tattoo Vixens - Lisa Luxe
Milan Tattoo Convention - 2011
Terry Bradley - Taming the Black Dog
The Fox & The Woodcutter - Henrik Gallon
Closer to the Edge - Emil Edge
Picnic at Hanging Rock #4 - Craigy Lee
The Butcher's Hook - La Boucherie Moderne, Belgium
Tattoo Jam 2011 - Artist Skinpix
Adding a directory listing
Adding a tattoo artist profile
Adding an event
Big Tattoo Planet
1 Marcher Court
CH1 6BS

redpajama_set_name: RedPajamaCommonCrawl


text:
Sükösd Sámuel (Sepsiszentkirály, 1816. – Tömösi-szoros, 1849. június 20.) református lelkész, pap, író. Édesapja, Sükösd József is református lelkész volt.

Életpályája
Székelyudvarhelyen, Nagyenyeden tanult. 1831-ben lett főiskolás. 1838-ban köztanító lett. 1839-től püspöki titkárként dolgozott. 1840–1843 között Berlinben tanult tovább. 1843-ban Barátoson, 1844-ben Lécfalván, 1844-től Déván volt lelkész. 1848–1849 között Uzonban volt lelkipásztor. A Tömösi-szorost védő székely honvédek tábori papjaként halt hősi halált.

Művei
 A költészet alaprajza. Útmutatásul csupán kezdő tanítványai számára (verstan, Nagyenyed, 1839)
 Ez az élet csalódás (Gyászbeszéd Jakó Elekné Csoma Klára felett). (Brassó, 1843)
 Az iskolamester elhivattatása szép és fontos (Gyászbeszéd Veress István felett) (Brassó, 1844)
 Halotti beszédek (közzétette Baló Benjámin, Arad, 1858)

Jegyzetek

Források

 Elektronikus Könyvtár

További információk
 Nagy Sándor: Háromszék önvédelmi harca 1848 – 49-ben (Kolozsvár, 1896)
 Szinnyei József: Magyar írók élete és munkái. Budapest, 1891-1914. Hornyánszky Viktor

 Zakar Péter: A magyar hadsereg tábori lelkészei 1848-49-ben. Budapest, Magyar Egyháztörténeti Enciklopédia Munkaközösség, 1999.
 Zoványi Jenő: Magyarországi protestáns egyháztörténeti lexikon. Szerkesztette: Ladányi Sándor. 3. javított bővített kiadás. [Budapest], Magyar Református Egyház Zsinati Irodája, 1977.

1816-ban született személyek
1849-ben elhunyt személyek
Magyar írók
Magyar református lelkészek

redpajama_set_name: RedPajamaWikipedia


Gina Bianchini is the co-founder and CEO of Ning (www.ning.com), a platform for creating your own social network for anything. Prior to Ning, she was co-founder and president of Harmonic Communications which was acquired by Dentsu. She has also held positions at CKS Group and Goldman Sachs & Co. She has a B.A. from Stanford University and an M.B.A from Stanford Business School.


Joshua Udell gives a brutally honest look at what goes on in ..
Schizophrenia is one of the most misunderstood mental illnesses and yet 1 in 100 people suffer from it. Just what goes on inside the mind of a schizophrenic? Joshua Udell give insight into what goes on in my mind as a person with schizophrenia. A rare look into the frightening and alarming visions, hallucinations, delusions he has experienced. This true story shows hope for families of and those who suffer with mental illness.
What would you do if your mind was playing tricks on you? I for one have experienced the games schizophrenia can do if not careful. Joshua Udell has seen schizophrenia lead him down a path of confusion and chaos. Luckily, Mr. Udell has overcome with help from incredible people that have knocked down the powerful force within his mind to overcome. While there is no cure, there is help and fortunately the paranoia has been nearly swallowed up in the battle between darkness and light to the pathway to surviving and recovery.
Since Joshua and his wife Lindsay got married, it has been one of their family's goals to share and educate on issues regarding mental illnesses. Joshua Udell would like to change the stigmas that surround the most misunderstood mental illness, schizophrenia and hope this book will help.
Joshua Udell is a successful husband, father, writer, teacher and minister battling with schizophrenia. Joshua received his bachelors degree in Biblical Literature from Ozark Christian College in Joplin, Missouri and is an ordained minister. Mr. Udell was born in Omaha, Nebraska on October 3rd 1979 and has been married since June of 2002 and enjoys family time with his wife Lindsay and son Jesse.
Joshua Udell grew up learning about Islam, Christianity, Judaism and Buddhism and is a writer of prophecy and many religious subjects. Mr. Udell has done funerals, weddings, and has preached in several states including overseas in Chang Mai, Thailand.
Joshua has traveled the world, lived in Riyadh, Saudi Arabia and has visited many countries including Egypt, Jordan, Israel, Bahrain. Scuba dived in the Red Sea and floated in the Dead Sea. Mr. Udell has also visited France, England, China (Hong Kong), Myanmar, Thailand, Laos and Mexico. Joshua currently resides in Webb City, Missouri.
My very good friend and neighbor knocked on my door, while I was wide awake laying on the couch engulfed by the television screen about a rapture that was going to happen any moment. As he interrupted my rapture preparations the strangest thoughts came to me as Porter asked me to accompany him to return some videos. I'm feeling lazy and prepared for anything the great disappearance of many people. Rapture I'm ready!
I am about to experience the rapture of all. I felt as the night is good for a walk to the video store or a rapture.
He invited and I insisted. We closed the door behind us and the next thing I knew no rapture happened, driving in my neighbors car, instead of walking I was wondering where he had rented his videos, apparently the hospital unit. Doctors confirmed my friend's fears and a few hours later, which seemed many more to me, a rapture did take place a disappearing where I was out cold, completely gone and in the twinkling of an eye I found myself in the hospital unit. I had disappeared, but it didn't seem like my television set had been describing, it was more like, a foggy dream lost, passed and a rapture of gobbledygook. Damn that television, I felt as if that's what happened to me this serene blustery night, but only as if a commercial interrupted all the perfection.
When it first began, I thought to myself, "What happened?" I didn't know what was going on. All I knew was that I felt as if something supernatural was taking place. As if God was in or mimicking me, or was it the other way around? As if I was doing the things that God wanted me to do. I was out of it or shall I say I was spacey. No one really mattered to me living in or on the seventh realm of life. The presence of awe-inspiring thoughts that were bouncing through my head as a racquetball bounces back and fourth. But eventually the game is over. That one still takes me a lot to realize. Because every so often it seems like the racquetball game keeps going, and at times gets louder and fearfully more competitive.
At other times, the mental images of past emotions and expressions that you have seen in your life make you feel broken and with no place to go to dry your eyes from the feelings that seem impossible to decode. You try and then you hear the words, "Are you in another episode?" Laughing I might think to myself, "Yes, this time it's the episode when Anakin Skywalker takes over the world." But so-called reality has to trickle in, which can actually be a deterring moment. A trouncing of your faith, battering your beliefs that this time you are too far gone or that this time you have departed to an empty terrain where the radar has broken and no one knows where you are.
I am not an ordinary individual, but neither was Van Gogh, Einstein, Mozart, and for that matter Poe or Louis Carroll. But everyone, maybe once in awhile, wants to be extravagant. After all movie stars, writers, musicians, and inventors are usually bizarre or odd people. People want to excel, my episodes have allowed me to accelerate an impressive story with facts and fiction of recollections.


text:
/*****************************************************************************/
/* File Implementing the shared memory system for Hack.
 *
 * THIS CODE ONLY WORKS WITH HACK, IT MAY LOOK LIKE A GENERIC ATOMIC
 * HASHTABLE FOR OCAML: IT IS NOT!
 * BUT ... YOU WERE GOING TO SAY BUT? BUT ...
 * THERE IS NO BUT! DONNY YOU'RE OUT OF YOUR ELEMENT!
 *
 * The lock-free data structures implemented here only work because of how
 * the Hack phases are synchronized.
 *
 * There are 3 kinds of storage implemented in this file.
 * I) The global storage. Used by the master to efficiently transfer a blob
 *    of data to the workers. This is used to share an environment in
 *    read-only mode with all the workers.
 *    The master stores, the workers read.
 *    Only concurrent reads allowed. No concurrent write/read and write/write.
 *    There are a few different OCaml modules that act as interfaces to this
 *    global storage. They all use the same area of memory, so only one can be
 *    active at any one time. The first word indicates the size of the global
 *    storage currently in use; callers are responsible for setting it to zero
 *    once they are done.
 *
 * II) The dependency table. It's a hashtable that contains all the
 *    dependencies between Hack objects. It is filled concurrently by
 *    the workers. The dependency table is made of 2 hashtables, one that
 *    can is used to quickly answer if a dependency exists. The other one
 *    to retrieve the list of dependencies associated with an object.
 *    Only the hashes of the objects are stored, so this uses relatively
 *    little memory. No dynamic allocation is required.
 *
 * III) The hashtable that maps string keys to string values. (The strings
 *    are really serialized / marshalled representations of OCaml structures.)
 *    Key observation of the table is that data with the same key are
 *    considered equivalent, and so you can arbitrarily get any copy of it;
 *    furthermore if data is missing it can be recomputed, so incorrectly
 *    saying data is missing when it is being written is only a potential perf
 *    loss. Note that "equivalent" doesn't necessarily mean "identical", e.g.,
 *    two alpha-converted types are "equivalent" though not literally byte-
 *    identical. (That said, I'm pretty sure the Hack typechecker actually does
 *    always write identical data, but the hashtable doesn't need quite that
 *    strong of an invariant.)
 *
 *    The operations implemented, and their limitations:
 *
 *    -) Concurrent writes: SUPPORTED
 *       One will win and the other will get dropped on the floor. There is no
 *       way to tell which happened. Only promise is that after a write, the
 *       one thread which did the write will see data in the table (though it
 *       may be slightly different data than what was written, see above about
 *       equivalent data).
 *
 *    -) Concurrent reads: SUPPORTED
 *       If interleaved with a concurrent write, the read will arbitrarily
 *       say that there is no data at that slot or return the entire new data
 *       written by the concurrent writer.
 *
 *    -) Concurrent removes: NOT SUPPORTED
 *       Only the master can remove, and can only do so if there are no other
 *       concurrent operations (reads or writes).
 *
 *    Since the values are variably sized and can get quite large, they are
 *    stored separately from the hashes in a garbage-collected heap.
 *
 * Both II and III resolve hash collisions via linear probing.
 */
/*****************************************************************************/

/* define CAML_NAME_SPACE to ensure all the caml imports are prefixed with
 * 'caml_' */
#define CAML_NAME_SPACE
#include <caml/mlvalues.h>
#include <caml/unixsupport.h>
#include <caml/memory.h>
#include <caml/alloc.h>
#include <caml/fail.h>

#include <assert.h>

#ifdef _WIN32
#include <windows.h>
#else
#include <fcntl.h>
#include <pthread.h>
#include <signal.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <sys/errno.h>
#include <sys/mman.h>
#include <sys/resource.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#endif

// The following 'typedef' won't be required anymore
// when dropping support for OCaml < 4.03
#ifdef __MINGW64__
typedef unsigned __int64 uint64_t;
#endif

#ifndef NO_LZ4
#include <lz4.h>
#include <lz4hc.h>
#endif

#ifdef _WIN32
static int win32_getpagesize(void)
{
  SYSTEM_INFO siSysInfo;
  GetSystemInfo(&siSysInfo);
  return siSysInfo.dwPageSize;
}
#define getpagesize win32_getpagesize
#endif

/*****************************************************************************/
/* Config settings (essentially constants, so they don't need to live in shared
 * memory), initialized in hh_shared_init */
/*****************************************************************************/

static size_t global_size_b;
static size_t heap_size;

// XXX: DEP_POW and HASHTBL_POW are not configurable because we take a ~2% perf
// hit by doing so, likely because the compiler does some constant folding.
// Should revisit this if / when we switch to compiling with an optimization
// level higher than -O0. In lieu of that, let's use a define so we don't use
// absurd amounts of RAM for OSS users.
#ifdef OSS_SMALL_HH_TABLE_POWS
#define DEP_POW         17
#define HASHTBL_POW     18
#else
#define DEP_POW         26
#define HASHTBL_POW     26
#endif

/* Convention: .*_B = Size in bytes. */

/* Used for the dependency hashtable */
#define DEP_SIZE        (1ul << DEP_POW)
#define DEP_SIZE_B      (DEP_SIZE * sizeof(value))

/* Used for the shared hashtable */
#define HASHTBL_SIZE    (1ul << HASHTBL_POW)
#define HASHTBL_SIZE_B  (HASHTBL_SIZE * sizeof(helt_t))

/* Size of where we allocate shared objects. */
#define Get_size(x)     (((size_t*)(x))[-1])
#define Get_buf_size(x) (((size_t*)(x))[-1] + sizeof(size_t))
#define Get_buf(x)      (x - sizeof(size_t))

/* Too lazy to use getconf */
#define CACHE_LINE_SIZE (1 << 6)
#define CACHE_MASK      (~(CACHE_LINE_SIZE - 1))
#define ALIGNED(x)      ((x + CACHE_LINE_SIZE - 1) & CACHE_MASK)

/* As a sanity check when loading from a file */
static uint64_t MAGIC_CONSTANT = 0xfacefacefaceb000ll;

/* The VCS identifier (typically a git hash) of the build */
extern const char* const BuildInfo_kRevision;

/*****************************************************************************/
/* Types */
/*****************************************************************************/

/* Cells of the Hashtable */
typedef struct {
  uint64_t hash;
  char* addr;
} helt_t;

/*****************************************************************************/
/* Globals */
/*****************************************************************************/

/* Total size of allocated shared memory */
static size_t shared_mem_size;

/* Beginning of shared memory */
static char* shared_mem = NULL;

/* ENCODING: The first element is the size stored in bytes, the rest is
 * the data. The size is set to zero when the storage is empty.
 */
static value* global_storage;

/* ENCODING:
 * The highest 2 bits are unused.
 * The next 31 bits encode the key the lower 31 bits the value.
 */
static uint64_t* deptbl;
static uint64_t* deptbl_bindings;

/* The hashtable containing the shared values. */
static helt_t* hashtbl;
static int* hcounter;   // the number of slots taken in the table

/* A counter increasing globally across all forks. */
static uintptr_t* counter;
/* This should only be used before forking */
static uintptr_t early_counter = 1;

/* The top of the heap */
static char** heap;

/* Useful to add assertions */
static pid_t master_pid;
static pid_t my_pid;

/* Where the heap started (bottom) */
static char* heap_init;

/* The size of the heap after initialization of the server */
/* This should only be used by the master */
static size_t heap_init_size = 0;

static size_t used_heap_size(void) {
  return *heap - heap_init;
}

/* Expose so we can display diagnostics */
CAMLprim value hh_heap_size(void) {
  CAMLparam0();
  CAMLreturn(Val_long(used_heap_size()));
}

CAMLprim value hh_hash_used_slots(void) {
  CAMLparam0();
  uint64_t count = 0;
  uintptr_t i = 0;
  for (i = 0; i < HASHTBL_SIZE; ++i) {
    if (hashtbl[i].addr != NULL) {
      count++;
    }
  }
  CAMLreturn(Val_long(count));
}

CAMLprim value hh_hash_slots(void) {
  CAMLparam0();
  CAMLreturn(Val_long(HASHTBL_SIZE));
}

struct timeval log_duration(const char *prefix, struct timeval start_t) {
  struct timeval end_t;
  gettimeofday(&end_t, NULL);
  time_t secs = end_t.tv_sec - start_t.tv_sec;
  suseconds_t usecs = end_t.tv_usec - start_t.tv_usec;
  double time_taken = secs + ((double)usecs / 1000000);
  fprintf(stderr, "%s took %.2lfs\n", prefix, time_taken);
  return end_t;
}

/*****************************************************************************/
/* Given a pointer to the shared memory address space, initializes all
 * the globals that live in shared memory.
 */
/*****************************************************************************/

static void init_shared_globals(char* mem) {
  size_t page_size = getpagesize();

#ifdef _WIN32
  if (!VirtualAlloc(mem,
                    page_size + global_size_b +
                      2 * DEP_SIZE_B + HASHTBL_SIZE_B,
                    MEM_COMMIT, PAGE_READWRITE)) {
    win32_maperr(GetLastError());
    uerror("VirtualAlloc2", Nothing);
  }
#endif

  /* BEGINNING OF THE SMALL OBJECTS PAGE
   * We keep all the small objects in this page.
   * They are on different cache lines because we modify them atomically.
   */

  /* The pointer to the top of the heap.
   * We will atomically increment *heap every time we want to allocate.
   */
  heap = (char**)mem;

  // The number of elements in the hashtable
  assert(CACHE_LINE_SIZE >= sizeof(int));
  hcounter = (int*)(mem + CACHE_LINE_SIZE);
  *hcounter = 0;

  assert (CACHE_LINE_SIZE >= sizeof(uintptr_t));
  counter = (uintptr_t*)(mem + 2*CACHE_LINE_SIZE);
  *counter = early_counter + 1;

  mem += page_size;
  // Just checking that the page is large enough.
  assert(page_size > 2*CACHE_LINE_SIZE + (int)sizeof(int));
  /* END OF THE SMALL OBJECTS PAGE */

  /* Global storage initialization */
  global_storage = (value*)mem;
  // Initial size is zero
  global_storage[0] = 0;
  mem += global_size_b;

  /* Dependencies */
  deptbl = (uint64_t*)mem;
  mem += DEP_SIZE_B;

  deptbl_bindings = (uint64_t*)mem;
  mem += DEP_SIZE_B;

  /* Hashtable */
  hashtbl = (helt_t*)mem;
  mem += HASHTBL_SIZE_B;

  /* Heap */
  heap_init = mem;
  *heap = mem;
}

/*****************************************************************************/
/* Must be called by the master BEFORE forking the workers! */
/*****************************************************************************/

CAMLprim value hh_shared_init(
  value global_size_val,
  value heap_size_val
) {

  CAMLparam2(global_size_val, heap_size_val);

  global_size_b = Long_val(global_size_val);
  heap_size = Long_val(heap_size_val);

  size_t page_size = getpagesize();

  /* The total size of the shared memory.  Most of it is going to remain
   * virtual. */
  shared_mem_size =
    global_size_b + 2 * DEP_SIZE_B + HASHTBL_SIZE_B +
    heap_size + page_size;

#ifdef _WIN32
  /*

     We create an anonymous memory file, whose `handle` might be
     inherited by slave processes.

     This memory file is tagged "reserved" but not "committed". This
     means that the memory space will be reserved in the virtual
     memory table but the pages will not be bound to any physical
     memory yet. Further calls to 'VirtualAlloc' will "commit" pages,
     meaning they will be bound to physical memory.

     This is behavior that should reflect the 'MAP_NORESERVE' flag of
     'mmap' on Unix. But, on Unix, the "commit" is implicit.

     Committing the whole shared heap at once would require the same
     amount of free space in memory (or in swap file).

  */
  HANDLE handle = CreateFileMapping(
    INVALID_HANDLE_VALUE,
    NULL,
    PAGE_READWRITE | SEC_RESERVE,
    shared_mem_size >> 32, shared_mem_size & ((1ll << 32) - 1),
    NULL);
  if (handle == NULL) {
    win32_maperr(GetLastError());
    uerror("CreateFileMapping", Nothing);
  }
  if (!SetHandleInformation(handle, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT)) {
    win32_maperr(GetLastError());
    uerror("SetHandleInformation", Nothing);
  }
  shared_mem = MapViewOfFileEx(
    handle,
    FILE_MAP_ALL_ACCESS,
    0, 0, 0);
  if (shared_mem == NULL) {
    win32_maperr(GetLastError());
    uerror("MapViewOfFileEx", Nothing);
  }

#else /* _WIN32 */

  /* MAP_NORESERVE is because we want a lot more virtual memory than what
   * we are actually going to use.
   */
  int flags = MAP_SHARED | MAP_ANON | MAP_NORESERVE;
  int prot  = PROT_READ  | PROT_WRITE;

  shared_mem = (char*)mmap(NULL, shared_mem_size, prot, flags, 0, 0);
  if(shared_mem == MAP_FAILED) {
    printf("Error initializing: %s\n", strerror(errno));
    exit(2);
  }

#ifdef MADV_DONTDUMP
  // We are unlikely to get much useful information out of the shared heap in
  // a core file. Moreover, it can be HUGE, and the extensive work done dumping
  // it once for each CPU can mean that the user will reboot their machine
  // before the much more useful stack gets dumped!
  madvise(shared_mem, shared_mem_size, MADV_DONTDUMP);
#endif

  // Keeping the pids around to make asserts.
  master_pid = getpid();
  my_pid = master_pid;

#endif /* _WIN32 */

  char* bottom = shared_mem;
  init_shared_globals(shared_mem);

  // Checking that we did the maths correctly.
  assert(*heap + heap_size == bottom + shared_mem_size);

#ifndef _WIN32
  // Uninstall ocaml's segfault handler. It's supposed to throw an exception on
  // stack overflow, but we don't actually handle that exception, so what
  // happens in practice is we terminate at toplevel with an unhandled exception
  // and a useless ocaml backtrace. A core dump is actually more useful. Sigh.
  struct sigaction sigact;
  sigact.sa_handler = SIG_DFL;
  sigemptyset(&sigact.sa_mask);
  sigact.sa_flags = 0;
  sigaction(SIGSEGV, &sigact, NULL);
#endif

  CAMLreturn(Val_unit);
}

void hh_shared_reset() {
#ifndef _WIN32
  assert(shared_mem);
  early_counter = 1;
  memset(shared_mem, 0, heap_init - shared_mem);
  init_shared_globals(shared_mem);
#endif
}

/* Must be called by every worker before any operation is performed */
void hh_worker_init() {
#ifndef _WIN32
  my_pid = getpid();
#endif
}

/*****************************************************************************/
/* Counter
 *
 * Provides a counter intended to be increasing over the lifetime of the program
 * including all forks. Uses a global variable until hh_shared_init is called,
 * so it's safe to use in the early init stages of the program (as long as you
 * fork after hh_shared_init of course). Wraps around at the maximum value of an
 * ocaml int, which is something like 30 or 62 bits on 32 and 64-bit
 * architectures respectively.
 */
/*****************************************************************************/

CAMLprim value hh_counter_next(void) {
  CAMLparam0();
  CAMLlocal1(result);

  uintptr_t v;
  if (counter) {
    v = __sync_fetch_and_add(counter, 1);
  } else {
    v = ++early_counter;
  }

  result = Val_long(v % Max_long); // Wrap around.
  CAMLreturn(result);
}

/*****************************************************************************/
/* Global storage */
/*****************************************************************************/

void hh_shared_store(value data) {
  CAMLparam1(data);
  size_t size = caml_string_length(data);

  assert(my_pid == master_pid);                  // only the master can store
  assert(global_storage[0] == 0);                // Is it clear?
  assert(size < global_size_b - sizeof(value));  // Do we have enough space?

  global_storage[0] = size;
  memcpy(&global_storage[1], &Field(data, 0), size);

  CAMLreturn0;
}

/*****************************************************************************/
/* We are allocating ocaml values. The OCaml GC must know about them.
 * caml_alloc_string might trigger the GC, when that happens, the GC needs
 * to scan the stack to find the OCaml roots. The macros CAMLparam0 and
 * CAMLlocal1 register the roots.
 */
/*****************************************************************************/

CAMLprim value hh_shared_load(void) {
  CAMLparam0();
  CAMLlocal1(result);

  size_t size = global_storage[0];
  assert(size != 0);
  result = caml_alloc_string(size);
  memcpy(&Field(result, 0), &global_storage[1], size);

  CAMLreturn(result);
}

void hh_shared_clear(void) {
  assert(my_pid == master_pid);
  global_storage[0] = 0;
}

/*****************************************************************************/
/* Dependencies */
/*****************************************************************************/
/* This code is very perf sensitive, please check the performance before
 * modifying.
 * The table contains key/value bindings encoded in a word.
 * The higher bits represent the key, the lower ones the value.
 * Each key/value binding is unique, but a key can have multiple value
 * bound to it.
 * Concretely, if you try to add a key/value pair that is already in the table
 * the data structure is left unmodified.
 * If you try to add a key bound to a new value, the binding is added, the
 * old binding is not removed.
 */
/*****************************************************************************/

static int htable_add(uint64_t* table, unsigned long hash, uint64_t value) {
  unsigned long slot = hash & (DEP_SIZE - 1);

  while(1) {
    /* It considerably speeds things up to do a normal load before trying using
     * an atomic operation.
     */
    uint64_t slot_val = table[slot];

    // The binding exists, done!
    if(slot_val == value)
      return 0;

    // The slot is free, let's try to take it.
    if(slot_val == 0) {
      // See comments in hh_add about its similar construction here.
      if(__sync_bool_compare_and_swap(&table[slot], 0, value)) {
        return 1;
      }

      if(table[slot] == value) {
        return 0;
      }
    }

    slot = (slot + 1) & (DEP_SIZE - 1);
  }
}

void hh_add_dep(value ocaml_dep) {
  CAMLparam1(ocaml_dep);
  uint64_t dep = Long_val(ocaml_dep);
  unsigned long hash = (dep >> 31) * (dep & ((1ul << 31) - 1));

  if(!htable_add(deptbl_bindings, hash, hash)) {
    CAMLreturn0;
  }

  htable_add(deptbl, dep >> 31, dep);

  CAMLreturn0;
}

CAMLprim value hh_dep_used_slots(void) {
  CAMLparam0();
  uint64_t count = 0;
  uintptr_t slot = 0;
  for (slot = 0; slot < DEP_SIZE; ++slot) {
    if (deptbl[slot]) {
      count++;
    }
  }
  CAMLreturn(Val_long(count));
}

CAMLprim value hh_dep_slots(void) {
  CAMLparam0();
  CAMLreturn(Val_long(DEP_SIZE));
}

/* Given a key, returns the list of values bound to it. */
CAMLprim value hh_get_dep(value dep) {
  CAMLparam1(dep);
  CAMLlocal2(result, cell);

  unsigned long hash = Long_val(dep);
  unsigned long slot = hash & (DEP_SIZE - 1);

  result = Val_int(0); // The empty list

  while(1) {
    if(deptbl[slot] == 0) {
      break;
    }
    if(deptbl[slot] >> 31 == hash) {
      cell = caml_alloc_tuple(2);
      Field(cell, 0) = Val_long(deptbl[slot] & ((1ul << 31) - 1));
      Field(cell, 1) = result;
      result = cell;
    }
    slot = (slot + 1) & (DEP_SIZE - 1);
  }

  CAMLreturn(result);
}

/*****************************************************************************/
/* Garbage collector */
/*****************************************************************************/

/*****************************************************************************/
/* Must be called after the hack server is done initializing.
 * We keep the original size of the heap to estimate how often we should
 * garbage collect.
 */
/*****************************************************************************/
void hh_call_after_init() {
  CAMLparam0();
  heap_init_size = used_heap_size();
  if(2 * heap_init_size >= heap_size) {
    caml_failwith("Heap init size is too close to max heap size; "
      "GC will never get triggered!");
  }
  CAMLreturn0;
}

/*****************************************************************************/
/* We compact the heap when it gets twice as large as its initial size.
 * Step one, copy the live values in a new heap.
 * Step two, memcopy the values back into the shared heap.
 * We could probably use something smarter, but this is fast enough.
 *
 * The collector should only be called by the master.
 */
/*****************************************************************************/
void hh_collect(value aggressive_val) {
#ifdef _WIN32
  // TODO GRGR
  return;
#else
  int aggressive  = Bool_val(aggressive_val);
  int flags       = MAP_PRIVATE | MAP_ANON | MAP_NORESERVE;
  int prot        = PROT_READ | PROT_WRITE;
  char* dest;
  size_t mem_size = 0;
  char* tmp_heap;

  float space_overhead = aggressive ? 1.2 : 2.0;
  if(used_heap_size() < (size_t)(space_overhead * heap_init_size)) {
    // We have not grown past twice the size of the initial size
    return;
  }

  tmp_heap = (char*)mmap(NULL, heap_size, prot, flags, 0, 0);
  dest = tmp_heap;

  if(tmp_heap == MAP_FAILED) {
    printf("Error while collecting: %s\n", strerror(errno));
    exit(2);
  }

  assert(my_pid == master_pid); // Comes from the master

  // Walking the table
  size_t i;
  for(i = 0; i < HASHTBL_SIZE; i++) {
    if(hashtbl[i].addr != NULL) { // Found a non empty slot
      size_t bl_size      = Get_buf_size(hashtbl[i].addr);
      size_t aligned_size = ALIGNED(bl_size);
      char* addr          = Get_buf(hashtbl[i].addr);

      memcpy(dest, addr, bl_size);
      // This is where the data ends up after the copy
      hashtbl[i].addr = heap_init + mem_size + sizeof(size_t);
      dest     += aligned_size;
      mem_size += aligned_size;
    }
  }

  // Copying the result back into shared memory
  memcpy(heap_init, tmp_heap, mem_size);
  *heap = heap_init + mem_size;

  if(munmap(tmp_heap, heap_size) == -1) {
    printf("Error while collecting: %s\n", strerror(errno));
    exit(2);
  }
#endif
}

/*****************************************************************************/
/* Allocates in the shared heap.
 * The chunks are cache aligned.
 * The word before the chunk address contains the size of the chunk in bytes.
 * The function returns a pointer to the data (the size can be accessed by
 * looking at the address: chunk - sizeof(size_t)).
 */
/*****************************************************************************/

static char* hh_alloc(size_t size) {
  size_t slot_size  = ALIGNED(size + sizeof(size_t));
  char* chunk       = __sync_fetch_and_add(heap, (char*)slot_size);
#ifdef _WIN32
  if (!VirtualAlloc(chunk, slot_size, MEM_COMMIT, PAGE_READWRITE)) {
    win32_maperr(GetLastError());
    uerror("VirtualAlloc1", Nothing);
  }
#endif
  *((size_t*)chunk) = size;
  return (chunk + sizeof(size_t));
}

/*****************************************************************************/
/* Allocates an ocaml value in the shared heap.
 * The values can only be ocaml strings. It returns the address of the
 * allocated chunk.
 */
/*****************************************************************************/
static char* hh_store_ocaml(value data) {
  size_t data_size = caml_string_length(data);
  char* addr = hh_alloc(data_size);
  memcpy(addr, String_val(data), data_size);
  return addr;
}

/*****************************************************************************/
/* Given an OCaml string, returns the 8 first bytes in an unsigned long.
 * The key is generated using MD5, but we only use the first 8 bytes because
 * it allows us to use atomic operations.
 */
/*****************************************************************************/
static unsigned long get_hash(value key) {
  return *((unsigned long*)String_val(key));
}

/*****************************************************************************/
/* Writes the data in one of the slots of the hashtable. There might be
 * concurrent writers, when that happens, the first writer wins.
 */
/*****************************************************************************/
static void write_at(unsigned int slot, value data) {
  // Try to write in a value to indicate that the data is being written.
  if(hashtbl[slot].addr == NULL &&
     __sync_bool_compare_and_swap(&(hashtbl[slot].addr), NULL, (char*)1)) {
    hashtbl[slot].addr = hh_store_ocaml(data);
  }
}

/*****************************************************************************/
/* Adds a key value to the hashtable. This code is perf sensitive, please
 * check the perf before modifying.
 */
/*****************************************************************************/
void hh_add(value key, value data) {
  unsigned long hash = get_hash(key);
  unsigned int slot = hash & (HASHTBL_SIZE - 1);

  while(1) {
    unsigned long slot_hash = hashtbl[slot].hash;

    if(slot_hash == hash) {
      write_at(slot, data);
      return;
    }

    if(slot_hash == 0) {
      // We think we might have a free slot, try to atomically grab it.
      if(__sync_bool_compare_and_swap(&(hashtbl[slot].hash), 0, hash)) {
        unsigned long size = __sync_fetch_and_add(hcounter, 1);
        assert(size < HASHTBL_SIZE);
        write_at(slot, data);
        return;
      }

      // Grabbing it failed -- why? If someone else is trying to insert
      // the data we were about to, try to insert it ourselves too.
      // Otherwise, keep going.
      // Note that this read relies on the __sync call above preventing the
      // compiler from caching the value read out of memory. (And of course
      // isn't safe on any arch that requires memory barriers.)
      if(hashtbl[slot].hash == hash) {
        // Some other thread already grabbed this slot to write this
        // key, but they might not have written the address (or even
        // the sigil value) yet. We can't return from hh_add until we
        // know that hh_mem would succeed, which is to say that addr is
        // no longer null. To make sure hh_mem will work, we try
        // writing the value ourselves; either we insert it ourselves or
        // we know the address is now non-NULL.
        write_at(slot, data);
        return;
      }
    }

    slot = (slot + 1) & (HASHTBL_SIZE - 1);
  }
}

/*****************************************************************************/
/* Finds the slot corresponding to the key in a hash table. The returned slot
 * is either free or points to the key.
 */
/*****************************************************************************/
static unsigned int find_slot(value key) {
  unsigned long hash = get_hash(key);
  unsigned int slot = hash & (HASHTBL_SIZE - 1);

  while(1) {
    if(hashtbl[slot].hash == hash) {
      return slot;
    }
    if(hashtbl[slot].hash == 0) {
      return slot;
    }
    slot = (slot + 1) & (HASHTBL_SIZE - 1);
  }
}

/*****************************************************************************/
/* Returns true if the key is present. We need to check both the hash and
 * the address of the data. This is due to the fact that we remove by setting
 * the address slot to NULL (we never remove a hash from the table, outside
 * of garbage collection).
 */
/*****************************************************************************/
value hh_mem(value key) {
  unsigned int slot = find_slot(key);
  if(hashtbl[slot].hash == get_hash(key) &&
     hashtbl[slot].addr != NULL) {
    // The data is currently in the process of being written, wait until it
    // actually is ready to be used before returning.
    while (hashtbl[slot].addr == (char*)1) {
      asm volatile("pause" : : : "memory");
    }
    return Val_bool(1);
  }
  return Val_bool(0);
}

/*****************************************************************************/
/* Returns the value associated to a given key. The key MUST be present. */
/*****************************************************************************/
CAMLprim value hh_get(value key) {
  CAMLparam1(key);
  CAMLlocal1(result);

  unsigned int slot = find_slot(key);
  assert(hashtbl[slot].hash == get_hash(key));
  size_t size = *(size_t*)(hashtbl[slot].addr - sizeof(size_t));
  result = caml_alloc_string(size);
  memcpy(String_val(result), hashtbl[slot].addr, size);

  CAMLreturn(result);
}

/*****************************************************************************/
/* Moves the data associated to key1 to key2.
 * key1 must be present.
 * key2 must be free.
 * Only the master can perform this operation.
 */
/*****************************************************************************/
void hh_move(value key1, value key2) {
  unsigned int slot1 = find_slot(key1);
  unsigned int slot2 = find_slot(key2);

  assert(my_pid == master_pid);
  assert(hashtbl[slot1].hash == get_hash(key1));
  assert(hashtbl[slot2].addr == NULL);
  hashtbl[slot2].hash = get_hash(key2);
  hashtbl[slot2].addr = hashtbl[slot1].addr;
  hashtbl[slot1].addr = NULL;
}

/*****************************************************************************/
/* Removes a key from the hash table.
 * Only the master can perform this operation.
 */
/*****************************************************************************/
void hh_remove(value key) {
  unsigned int slot = find_slot(key);

  assert(my_pid == master_pid);
  assert(hashtbl[slot].hash == get_hash(key));
  hashtbl[slot].addr = NULL;
}

/*****************************************************************************/
/* Saved State */
/*****************************************************************************/

#ifdef NO_LZ4
void hh_save_dep_table(value out_filename) {
  CAMLparam1(out_filename);
  caml_failwith("Program not linked with lz4, so saving is not supported!");
  CAMLreturn0;
}

void hh_load_dep_table(value in_filename) {
  CAMLparam1(in_filename);
  caml_failwith("Program not linked with lz4, so loading is not supported!");
  CAMLreturn0;
}
#else
static void fwrite_no_fail(
  const void* ptr, size_t size, size_t nmemb, FILE* fp
) {
  size_t nmemb_written = fwrite(ptr, size, nmemb, fp);
  assert(nmemb_written == nmemb);
}

/* We want to use read() instead of fread() for the large shared memory block
 * because buffering slows things down. This means we cannot use fread() for
 * the other (smaller) values in our file either, because the buffering can
 * move the file position indicator ahead of the values read. */
static void read_all(int fd, void* start, size_t size) {
  size_t total_read = 0;
  do {
    void* ptr = (void*)((uintptr_t)start + total_read);
    ssize_t bytes_read = read(fd, (void*)ptr, size);
    assert(bytes_read != -1 && bytes_read != 0);
    total_read += bytes_read;
  } while (total_read < size);
}

static void fwrite_header(FILE* fp) {
  fwrite_no_fail(&MAGIC_CONSTANT, sizeof MAGIC_CONSTANT, 1, fp);

  size_t revlen = strlen(BuildInfo_kRevision);
  fwrite_no_fail(&revlen, sizeof revlen, 1, fp);
  fwrite_no_fail(BuildInfo_kRevision, sizeof(char), revlen, fp);
}

static void fread_header(FILE* fp) {
  uint64_t magic = 0;
  read_all(fileno(fp), (void*)&magic, sizeof magic);
  assert(magic == MAGIC_CONSTANT);

  size_t revlen = 0;
  read_all(fileno(fp), (void*)&revlen, sizeof revlen);
  char revision[revlen];
  if (revlen > 0) {
    read_all(fileno(fp), (void*)revision, revlen * sizeof(char));
    assert(strncmp(revision, BuildInfo_kRevision, revlen) == 0);
  }
}

void hh_save_dep_table(value out_filename) {
  CAMLparam1(out_filename);
  FILE* fp = fopen(String_val(out_filename), "wb");

  fwrite_header(fp);

  int compressed_size = 0;

  assert(LZ4_MAX_INPUT_SIZE >= DEP_SIZE_B);
  char* compressed = malloc(DEP_SIZE_B);
  assert(compressed != NULL);

  compressed_size = LZ4_compressHC((char*)deptbl, compressed, DEP_SIZE_B);
  assert(compressed_size > 0);

  fwrite_no_fail(&compressed_size, sizeof compressed_size, 1, fp);
  fwrite_no_fail((void*)compressed, 1, compressed_size, fp);
  free(compressed);

  fclose(fp);
  CAMLreturn0;
}

void hh_load_dep_table(value in_filename) {
  CAMLparam1(in_filename);
  struct timeval tv;
  gettimeofday(&tv, NULL);

  FILE* fp = fopen(String_val(in_filename), "rb");

  if (fp == NULL) {
    unix_error(errno, "fopen", in_filename);
  }

  fread_header(fp);

  int compressed_size = 0;
  read_all(fileno(fp), (void*)&compressed_size, sizeof compressed_size);

  char* compressed = malloc(compressed_size * sizeof(char));
  assert(compressed != NULL);
  read_all(fileno(fp), compressed, compressed_size * sizeof(char));

  int actual_compressed_size = LZ4_decompress_fast(
      compressed,
      (char*)deptbl,
      DEP_SIZE_B);
  assert(compressed_size == actual_compressed_size);
  tv = log_duration("Loading file", tv);

  uintptr_t slot = 0;
  unsigned long hash = 0;
  for (slot = 0; slot < DEP_SIZE; ++slot) {
    hash = deptbl[slot];
    if (hash != 0) {
      htable_add(deptbl_bindings, hash, hash);
    }
  }

  fclose(fp);

  log_duration("Bindings", tv);
  CAMLreturn0;
}

#endif

redpajama_set_name: RedPajamaGithub


text:
Published by dan@waldenconsultants.com on November 9, 2020 November 9, 2020
LOS ANGELES (Legal Newsline) – Lawyers who spent more than a decade pursuing a whistleblower case that was almost entirely obliterated by a judge's ruling earlier this year are now chasing after the real payoff: Tens of millions of dollars in fees for a lawsuit that has yielded their clients $192,000.
In a filing in federal court in California, law firms that specialize in qui tam litigation – fraud suits by private citizens in the name of the government – have asked U.S. District Judge George H. Wu to award them fees for winning the long-running case against JM Eagle, the world's largest manufacturer of plastic pipe.
There's only one problem with their request: They lost. In a July order, Judge Wu dismissed damages claims against JM Eagle, finding the plaintiffs failed to present any evidence they had lost money and their experts couldn't prove the company's pipe was defective. In a confusing move, the judge left intact an earlier jury verdict finding the company liable for selling an unspecified amount of pipe that didn't meet industry standards and ordered the company to pay statutory penalties to five plaintiffs.
JM Eagle argues that verdict is illogical, since no company can guarantee 100% compliance on every product it makes, and the judge's ruling throwing out any possibility of damages has decided the case in its favor.
"This case was gone when Judge Wu issued his order dismissing it," said JM Eagle's attorney David Bernick of Paul Weiss, a veteran of numerous high-profile mass tort cases including breast implants and tobacco. "And for a case where the plaintiffs got zero, we feel the plaintiffs' lawyers shouldn't get anything more."
Attorney Elizabeth Sher with Day Pitney, one of several law firms representing government plaintiffs in the case, said the judge's award of statutory penalties means they won.
"There is no question that plaintiffs prevailed," plaintiff lawyers said in a Nov. 4 filing requesting fees. The judge refused to set aside a jury finding of liability, they argue, and his award of statutory penalties constitute "proceeds" of the lawsuit, triggering provisions of state and federal whistleblower laws requiring the defendant to pay the other side's legal costs. Given JM Eagle says it has spent more than $50 million on the case so far, fees could easily be in the tens of millions of dollars.
The fight over legal fees comes after a draining, 14-year legal war that began when John W. Hendrix, an engineer with JM Eagle, accused the company of manufacturing shoddy PVC pipe that had been installed in municipal water systems all over the country. JM Eagle is owned by Walter Wang, the youngest son of the late Taiwanese billionaire Y.C. Wang, who built that nation's plastics industry and controlled giant Formosa Plastics. Walter bought JM, a spinout from bankrupt asbestos manufacturer Johns-Manville, from Formosa in 2007 and built it into the world's largest manufacturer of PVC pipe through acquisitions and internal growth.
Hendrix launched his suit with what has a typical publicity tool for qui tam lawyers: A flattering profile in the New York Times presenting his side of the case. Not mentioned in that story was the fact the federal government had taken a pass on the lawsuit after testing JM Eagle pipe and finding it wasn't defective. Later, JM Eagle alleged in a lawsuit against Hendrix and his lawyers that Hendrix stole thousands of internal documents and had been fired not for whistleblowing, but for seeking a shakedown from a customer who supplied an affidavit describing the alleged attempt. Hendrix denied wrongdoing.
The case initially was pursued by Phillips & Cohen, whose founder John Phillips literally helped write the 1986 law that made it easier for whistleblowers to win large damages and legal fees in qui tam suits. Phillips & Cohen dropped out in 2016 after the lead attorney on the JM Eagle case, Eric Havian, moved to Constantine Cannon.
Plaintiff lawyers sought unsuccessfully to block JM Eagle from obtaining the results of government testing on its pipe, claiming the attorney-client privilege. Despite this evidence, Judge Wu allowed the case to proceed, splitting it into two phases. In Phase One the jury would decide liability on behalf of five representative plaintiffs. In Phase Two another jury would determine damages owed thousands of other government entities that bought JM Eagle pipe.
Phase One ended in 2013 with the puzzling verdict that JM Eagle was liable for saying its pipe complied with industry standards when testimony by former employees and expert witnesses suggested that due to slipshod manufacturing processes, not every piece actually met those standards. The verdict was unusual because manufacturers offer warranties for the specific reason that not every product coming out of the factory can be in compliance. The jury apparently disregarded the fact plaintiffs couldn't point to any pipe failures except for a single occurrence JM Eagle said was due to an incorrectly performed pressure test before the line was installed.
At a hearing after Phase One ended, Judge Wu acknowledged he had lost control of the proceedings. He limited the liability finding to the five plaintiffs in that trial.
"Given what happened in the first phase of the trial, it is – you know, the dust settled, but I don't know what happened," he said then. The judge nevertheless allowed the case to proceed to Phase Two, which ended with a mistrial in November 2018 after the jury couldn't come to a verdict. JM Eagle moved for a judgment in its favor, saying the plaintiffs failed to present any evidence they bought defective pipe or had suffered losses because of it.
The judge granted their motion in July, saying the plaintiffs' expert witnesses incorrectly linked results from short-term strength tests JM Eagle performed on raw PVC and finished pipes to the expected lifetime of the pipe. There was no engineering basis for that conclusion, the judge said. Plaintiffs had failed to provide evidence "from which a reasonable jury could make a finding of an award of actual damages," the judge wrote.
That ruling, combined with Judge Wu's earlier decision that the Phase One liability finding applies only to five plaintiffs, leaves plaintiff lawyers back at the beginning with a highly unfavorable decision working against them. Other law firms have brought a class action on behalf of municipal pipe buyers, but Bernick said no additional evidence has been presented in that case so far. To restart the litigation, plaintiff lawyers will have to bring new cases, presumably with new evidence.
Those efforts could get a big financial assist if Judge Wu orders JM Eagle to pay the legal fees of the lawyers it has been fighting for 14 years. Plaintiff lawyers argue the federal False Claims Act and nearly identical laws in California, Nevada and Virginia all allow fees "if the action results in any relief." The provision was designed to encourage private citizens to pursue claims that could recover money for the government.
Judge Wu, in an Oct. 1 order, agreed with JM Eagle that the plaintiffs had failed to present evidence of any losses. But he criticized the company for continuing to insist it had done nothing wrong. The company's allegedly shoddy practices "spanned roughly a decade and potentially impacted a huge swath of the country, including critical infrastructure and water systems," the judge wrote. He ordered "mid-range" penalties of $132,000 for 22 California water projects and $30,000 for projects in Virginia and Nevada.
Plaintiff lawyers have asked to bump those penalties to $260,000 – plus what will likely be millions of dollars in fees spent obtaining that result. JM Eagle, meanwhile, vows to keep fighting. Wang, who grew up with his single mother in relative poverty in California after his billionaire father cut them off, acknowledged to the Los Angeles Times earlier this year that he may have been foolish to fight the well-funded qui tam bar for so long instead of settling, like Formosa did years ago.
He said settling the case would admit fault, and that would inevitably hurt the company's ability to sell pipe in the future.
"I could not possibly settle, so I fought on and fought on," he told the LA Times. "Even my sister and brother-in-law told me, 'Walter, you have to have an exit strategy.'"
Categories:	Our crazy tort system
MDLs were supposed to be a more efficient way of handling mass-tort lawsuits but unethical practices and the incentives of corporate defendants combine to deliver poor results to plaintiffs. As reported on Legal Newsline: PHILADELPHIA, Read more…
As published on Legal Newsline: NEWARK, N.J., May 8, 2020 – A litigation finance company whose colorful history includes a federal criminal investigation and a multiyear battle over millions of dollars in legal fees stemming Read more…


text:
DELIMITER $$

DROP FUNCTION IF EXISTS _rdebug_get_lock_name $$
CREATE FUNCTION _rdebug_get_lock_name(
  connection_id int unsigned,
  name_hint varchar(32)
  ) returns varchar(64)
DETERMINISTIC
NO SQL
SQL SECURITY INVOKER
COMMENT 'Return value of option in JS options format'

begin
  return CONCAT_WS('_', '__common_schema_rdebug_lock', connection_id, name_hint);
end $$

DELIMITER ;


To create Gigi's "Golden Goddess" look, Misha took inspiration from inspired icons such as Raquel Welch and Sofia Loren--as they're the perfect role models for bronze beauty.
Celebrity make-up artist, Misha Shahzada for BeautyFriend recently created Gigi Hadid's summer make up for The Daily Summer Magazine. Famed photographer Gilles Bensimon was on hand to photograph the cover and inside story.
The first step in creating the look was to aim for a natural sun-kissed look while not having Gigi appear overly tanned. To accomplish this, Misha used Perfect Body Perfection Gel in matte tan all over her body to create a soft and natural looking glow. According to Misha, "The product blends nicely and is easily buildable without looking too heavy or unnatural". In order to achieve a perfect finish, Misha recommends exfoliating the body first as this will allow for overall even application.
Next, she used a bronzing brush and simply dusted Maybelline's Mineral Power Bronzerall over the face. **TIP--always start with less and build if you need to** Misha also suggests when using nudes for color, to experiment with shades such as taupe, browns, pinks, etc., as nudes do not always have to consist of just beige tones.
To finish the "Golden Goddess" look, she added a pop of color with a red lip while most of the face was left natural. Misha opted for a matte red lip with Maybelline's "Keep up the Flame" paired with Color Sensational lip liner in "Red" which added a modern twist to Gigi's look without appearing overly "glam".


Reuters Health reports that a researcher in a Siberian virology laboratory died after pricking herself with a syringe containing Ebola virus, a spokeswoman from the lab said.
Most outbreaks have occurred in Africa, far from the Siberian lab where the senior technician was experimenting on guinea pigs when the accident happened on May 5, 2004. She died several weeks later.
The state-owned vector research center at Novosibirsk, located in Siberia, conducts research into deadly diseases such as SARS and anthrax.
Along with the Centers for Disease Control and Prevention (CDC), the laboratory is one of only two places with official stockpiles of smallpox, which killed around 300 million people in the last century.
After the accident, the woman was hospitalized in a ward specially equipped to contain virulent diseases. Anyone who came into contact with her was put under observation for three weeks.