. There quite a lot of fun for all the vacationers , like fishing at the river , experiencing wonderful scenes and other wonderful places to travel to. A perfect dining area for those who love food.
In Sault Ste . Marie , among the finest restaurants to eat is North 82. Steak is an extremely well-known local food item at North 82 , however if you prefer American or Canadian cuisine , then there are a lot of meals to relish. Open up for lunch time , evening meal and late-night meal , North 82 is a must-try as a tourist.
The city of Sault Ste . Marie is a popular vacation spot from years. And travelers from all over surely visit North 82. The guests enjoy every bite of their favorite dish offered here. The place presents a tourist-friendly ambience for the people with a penchant for adventure when it comes to food.
Spending quality time with your family members requires a comfortable and warm ambience and North 82 has it all. Whether it is an impressive family occasion or it is a family of 4 members , this place is simply the best choice for memorable experiences to be cherished eternally. Not just this , our lavish party areas are ideal for anniversary celebration and functions.
Do you have a good gang of buddies along in this city? North 82 is the best spot for beverages and lengthy chats.
Restaurants Near Me: The menu at North 82 undoubtedly leaves its visitors mesmerized . Everyone surely revels in his favorite dish here. All of the food items are actually rated competitively. The restaurant's extremely experienced and certified cooks assure to provide a great taste so that you get the worth for your money.
The staff at North 82 welcome all the guests with warmth which makes them feel relaxed as they are taught to do so. Since there are lots of holidaymakers visiting this place , the restaurant ensures the staff is competent to handle them properly.


text:
void FFTOctaveAnalyzer::setup(float samplingRate, int nBandsInTheFFT, int nAveragesPerOctave){

    samplingRate = samplingRate;
    nSpectrum = nBandsInTheFFT;
    spectrumFrequencySpan = (samplingRate / 2.0f) / (float)(nSpectrum);
    nAverages = nBandsInTheFFT;
    // fe:  2f for octave bands, sqrt(2) for half-octave bands, cuberoot(2) for third-octave bands, etc
    if (nAveragesPerOctave==0) // um, wtf?
		nAveragesPerOctave = 1;
    nAveragesPerOctave = nAveragesPerOctave;
    averageFrequencyIncrement = pow(2.0f, 1.0f/(float)(nAveragesPerOctave));

    // this isn't currently configurable (used once here then no effect), but here's some reasoning:
    // 43 is a good value if you want to approximate "computer" octaves: 44100/2/2/2/2/2/2/2/2/2/2
    // 55 is a good value if you'd rather approximate A-440 octaves: 440/2/2/2
    // 65 is a good value if you'd rather approximate "middle-C" octaves:  ~262/2/2
    // you could easily double it if you felt the lowest band was just rumble noise (as it probably is)
    // but don't go much smaller unless you have a huge fft window size (see below for more why)
    // keep in mind, if you change it, that the number of actual bands may change +/-1, and
    // for some values, the last averaging band may not be very useful (may extend above nyquist)
    firstOctaveFrequency = 55.0f;
    // for each spectrum[] bin, calculate the mapping into the appropriate average[] bin.
    // this gives us roughly log-sized averaging bins, subject to how "fine" the spectrum bins are.
    // with more spectrum bins, you can better map into the averaging bins (especially at low
    // frequencies) or use more averaging bins per octave.  with an fft window size of 2048,
    // sampling rate of 44100, and first octave around 55, that's about enough to do half-octave
    // analysis.  if you don't have enough spectrum bins to map adequately into averaging bins
    // at the requested number per octave then you'll end up with "empty" averaging bins, where
    // there is no spectrum available to map into it.  (so... if you have "nonreactive" averages,
    // either increase fft buffer size, or decrease number of averages per octave, etc)
    spe2avg = new int[nSpectrum];
    int avgidx = 0;
    float averageFreq = firstOctaveFrequency; // the "top" of the first averaging bin
    // we're looking for the "top" of the first spectrum bin, and i'm just sort of
    // guessing that this is where it is (or possibly spectrumFrequencySpan/2?)
    // ... either way it's probably close enough for these purposes
    float spectrumFreq = spectrumFrequencySpan;
    for (int speidx=0; speidx < nSpectrum; speidx++) {
		while (spectrumFreq > averageFreq) {
			avgidx++;
			averageFreq *= averageFrequencyIncrement;
		}
		spe2avg[speidx] = avgidx;
		spectrumFreq += spectrumFrequencySpan;
    }
    nAverages = avgidx;
    averages = new float[nAverages];
    peaks = new float[nAverages];
    peakHoldTimes = new int[nAverages];
    peakHoldTime = 0; // arbitrary
    peakDecayRate = 0.9f; // arbitrary
    linearEQIntercept = 1.0f; // unity -- no eq by default
    linearEQSlope = 0.0f; // unity -- no eq by default
}

void FFTOctaveAnalyzer::calculate(float * fftData){

	int last_avgidx = 0; // tracks when we've crossed into a new averaging bin, so store current average
    float sum = 0.0f; // running total of spectrum data
    int count = 0; // count of spectrums accumulated (for averaging)
    for (int speidx=0; speidx < nSpectrum; speidx++) {
		count++;
		sum += fftData[speidx] * (linearEQIntercept + (float)(speidx) * linearEQSlope);
		int avgidx = spe2avg[speidx];
		if (avgidx != last_avgidx) {

			for (int j = last_avgidx; j < avgidx; j++){
				averages[j] = sum / (float)(count);
			}
			count = 0;
			sum = 0.0f;
		}
		last_avgidx = avgidx;
    }
    // the last average was probably not calculated...
    if ((count > 0) && (last_avgidx < nAverages)){
		averages[last_avgidx] = sum / (float)(count);
	}

    // update the peaks separately
    for (int i=0; i < nAverages; i++) {
		if (averages[i] >= peaks[i]) {
			// save new peak level, also reset the hold timer
			peaks[i] = averages[i];
			peakHoldTimes[i] = peakHoldTime;
		} else {
			// current average does not exceed peak, so hold or decay the peak
			if (peakHoldTimes[i] > 0) {
				peakHoldTimes[i]--;
			} else {
				peaks[i] *= peakDecayRate;
			}
		}
    }
}

redpajama_set_name: RedPajamaGithub


This is not one of the "inspirational movies" review I give, because it's not typical inspirational movie. This one is much more intensive, dramatic, disturbing, thrilling! It's packed with award-winning actors, which makes you excited to watch it, because you expect amazing acting and performances for an award-winning movie.
The main character is played by Hugh Jackman, a father who teaches his family to be ready for disasters, keeping them safe and sound. But when visiting friends for Thanksgiving, his daughter Anna goes missing and he losses his mind in trying to find her. His wife cannot believe what happened, because he always made them feel protected and safe.
That's when the police detective Loki, played by Jake Gyllenhaal, steps in, as the detective who solved every crime and gets the results fast. This time, he doesn't get anything fast. The movie is over 2 hours long and he loses his tracks few times.
Their lead is the driver of an RV, who turns out to be mentally challenged, and released of charges, yet the concerned father believes this guy knows something. The torture shown is very disturbing. The performances of Viola Davis and Terrence Howard, the parents of the other girl who went missing along with Anna, seeing the kidnapped man, played by Paul Dano, are incredibly realistic as well. Makes you feel the pain and makes you sick!
The story is real. Children get kidnapped and missing every day. The characters with their extremes, although disturbing, are very true. There is nothing that a parent won't do, to get his child back. And, on the other hand, there is nothing more courageous than a child who wants to go home.
Overall, I loved the performances. It's no secret that these actors are great! Even the ones that get a minor roles and not much screen time, like Viola Davis or Melissa Leo, make the movie more intense. The movie could have been more edited at some places and by the end much was left for the imagination, a lot of the story was unfinished, but the point was made.
You have to watch this movie for the great performances. Close your eyes if you can't get through the torture and sickening parts, but watch the rest. The actors really gave it all!
Where's my daughter? Where's my daughter! Every day she's wondering why I'm not there, me! Not you!


Where in the world is Tim Drake? Red Robin faces a crossroads…escape the most devious prison ever devised, or find himself abandoned beyond time and space for all eternity! Not much of a choice, right? But when he finds out who is locked in there with him, Tim's world will change in ways he never imagined! Collects DETECTIVE COMICS #963-968.


I can't understand what crime did I commit, I did nothing... I was born like this...pale as death...no criminal instincts in being beautiful and strange... Why are you so unfair, grasping my wrists like that? I know what you want. I won't give it to you.
:) hope you can visit mine.


Freestyling over three of Pharell's most famous beats, Atlanta's Pryce shows off his smooth style. "Pharellx3" transitions through each of the classic productions with Pryce following elegantly. Without ever stumbling over a beat switch he gets off bar after bar with ease. This is far from the first time he's shown he's capable of creating a heater. A regular occurrence for the underrated artist. Promisingly enough his forthcoming project Not Afraid Of Heights is closer than ever. More Pryce soon.


In the present world, the Internet is considered to be the most suitable way that enables you to earn good bucks online. The online marketing business are provided a wide opportunity for almost everyone to earn some money and thus, increase their income. Just like SEO plays an important role in enabling your website to get high rank in the major search engines, similarly online marketing has made it all possible to earn huge amount of dollars even at the comfort of your home. Make sure you choose a suitable online option that enables you to boost your income very soon.
With the help of online marketing, you can earn quite a good amount of money in no time. Check out some advantages associated with online marketing.
You may choose viral marketing for the promotion of your products as well as services to several customers. Thus, when your clients may get immense satisfaction by using your products, it is obvious that he will speak about your products to various people. As such, you will be able to increase your number of potential customers. You'll also be able to earn good amount of profit with online marketing.
With the help of different social networking communities, you can interact with innumerable people and as such, you may share your views and thoughts with them. Also, listen to what they want to say. Thus, by taking active participation in these social networking websites, you can promote your products and services to several people. This in turn, will give you a suitable chance to increase your sales with time.
Affiliate marketing is undoubtedly a great way to earn some valuable dollars online without putting much hard-work. In affiliate marketing, it is the website owner who puts an advertisement of the products and services of the merchant in his/her website. Thus, when any products/services of the merchant gets sold or if even a lead gets generated, the website owner gets the chance to earn a small percentage of commission. Affiliate marketing helps you boost your income and in turn, improve your financial condition.
Online marketing enables you to earn extra money apart from your fixed income. You do not need to allot any fixed time to earn dollars with online marketing programs. As such, you can make the most use of your leisure time and earn some precious dollars.
NextSEO: Has This Technique Been Fruitful For The Website To Get Desired Result?


text:
REVIEW: Footloose at the New Victoria Theatre in Woking
A foyer; palpable with energy and filled with people singing within their groups; the same phrase over and over again. "Everybody cut footloose". The film of Footloose (1984) starring Kevin Bacon is a cult classic, and fans were eager for the start of the show to toe-tap their way through the evening. As it all kicked off with the unmistakable guitar riff written by Kenny Loggins, the excitement and energy in the audience only grew greater.
Footloose follows the story of Ren, a Chicago teenagers moves to small, secluded town called 'Bomont' in West Virginia, where rock music and dancing are banned after an unfortunate accident killed 4 young residents. His brash attitude and rebellious nature shakes up the younger people of the town and as he meets the Reverend's daughter, Ariel, things start to get even more complicated.
What makes this production so unique is the phenomenal cast of actor-musicians. With no formal orchestra, the music played throughout is by the cast members either sitting to the side of the scene, or integrated into the centre of the action on stage. It was a fabulously refreshing set-up. The sets and scenery made great use of the height of the theatre, and the lighting was electric (if you'll pardon the pun).
This show really is made up of knockout ensemble of actor-musos. Joanna Sawyer as Rusty was stunning. Her flawless vocals left audience members audibly gasping and she was the talk of the bar at the interval after her incredible singing during "Holding Out For A Hero".
As Ariel, Hannah Price lead the girls well and was a captivating stage-presence and commanded the focus of all her scenes. Her best moments came in the tender one-on-one conversations with Ren in Act II where Ariel's wounded side begins to show. Her chemistry with Luke Baker as Ren was wonderful. Individually, he was also exceptional; his vocals throughout the night were superb, but his crowning glory was his emotive, raw and powerful dance sequence to conclude Act I. There was a real flavour of Billy Elliott's "Angry Dance" and it gave me goosebumps.
Star attraction Gareth Gates (of Pop Idol fame) has proven himself a West End leading man in several productions over the years including Les Miserables, and Legally Blonde. As Willard, his characterisation was a very over-the-top and he definitely played for the laughs, but the audience lapped it up, and he went down a storm. He's a character full of surprises
and was a crowd favourite for sure. Footloose also features Nolan sister, Maureen as Vi Moore, Ariel's Mother. During a stunning trio performance of "Learning To Be Silent" featuring Ren's Mother, Ariel's Mother and Ariel, her vocals shon and the three ladies complimented each other's tone beautifully. This was my favourite song from the evening.
A trip to Footloose will leave you humming the tunes for days after. It's as catchy and energetic as ever, and filled with some of the brightest stars on the circuit. This production is refreshingly original and one you won't want to miss!
Review by Harriet Langdown
Click here to book tickets
Labels: Harriet Langdown

redpajama_set_name: RedPajamaCommonCrawl


Since 1995, Captain's Landing luxury menswear has been offering only the finest men's resort fashions found under one roof anywhere. We currently offer an eclectic collection of smart and comfortable men's apparel and accessories featuring men's resort and beach wear from exclusive brands such as Tori Richard, Kahala, Bamboo Cay, Hook and Tackle, Brighton Belts and much more. For only the best in men's resort lifestyle clothing that define both luxury and confident style, you've come to the right place… Captain's Landing.
Mon-Sat. 10 a.m.- 5:30 p.m.


Why do we need a muslin?
I hope that all of those who participate in the sew-along know the importance of a muslin. It's a replica of the future garment to which you'll be able to make all necessary adjustments and tweaks. Your muslin will help you modify and play around with your initial idea of the jacket you were dreaming of for so long!
For our muslin, we will be focusing on stitching lines, and the clearer they are the better. So first thing, you need to trace nicely your pattern. If you took Susan's Craftsy class The Couture Dress , you will have seen the kind of tracing paper she used. These are big ( 66cm x 99cm/ 26" x 39") pieces of wax tracing paper which leave very beautiful marks on your muslin. You can buy this paper on Richard the Thread website but they have a minimum order of $35 which equates to 3 sets of tracing paper. You might find it expensive, but it is definitely a good investment. One year after I purchased it, I am still using one sheet of each (mainly red and white) and I have to tell you that I do trace a lot. For each garment I make I probably trace 2 muslins on average, sometimes more. So if you think about a long term investment and high quality product, definitely buy this!
It's also important to transfer all markings onto your muslin including grain lines, waist lines, pocket placement (if there are any). There is no need to mark notches, though.
Leisa told me that A Fashionable Stitch also sells wax paper as well as Oliver S in case you don't want to commit to a $35 purchase. Also, both New York Mood and Pacific Trimming keep a significant stock in their shops.
It is very important to leave large seam allowances on your muslin. When fitting it, you might add significant changes requiring more fabric that you have planned for in the beginning. For instance, you might want to add more length to your jacket.
Again, if you know Susan's Craftsy lesson then you'll know the way she recommends to put it together. If not, I will explain.
Once your muslin is traced and all the markings are transferred, use the longest stitch to baste all the stitching lines (3.5 - 4) and all markings, including darts: the stitching lines are going to be your main reference. You need to thread-trace for a few reasons, one of which is to transfer the information on both sides of the muslin. Having each of your pieces thread-traced helps you to see and feel it from either side.
It's recommended that each thread-traced line is independent. It is also very important to write pattern pieces' names on your muslin and specify whether it's the left or right piece. If a piece is confusing and can look like both top and bottom, also indicate this on the muslin. I did this mistake on my couture sewing class with Susan and I suffered.
There is another way to put a muslin together, which I personally prefer to Susan's and which I use for my LFJ: let's call it industrial. This method is much faster and in most cases as efficient as the couture one. It won't make a big difference for our jacket because the jacket will sit rather loosely verses an evening gown, but also because we will do another fitting of the garment once it's quilted. So all of the necessary final tweaks and adjustments can be made then.
Fitting and Pattern Alternation: this books describes any possible pattern alteration you can think of. It cost a little bit of money, but with this book you won't need anything else. It will quickly become your go-to fitting guide.
Threads Magazine offers a series of articles about fitting, some of which will be helpful for our little jacket: bust, torso, arms.
There are a couple of Craftsy lessons dedicated to fitting: Sew the Perfect Fit, Fast-Track Fitting. Personally, I have not tired them, but if you have and would like to share with us how they are, please go ahead!
To mark all possible alteration, I use a soft-tip pen or marker. On the photos below, I'll show you my alteration and how I dealt with them.
I chose to work with a Burda pattern #109 from 03/2012: no princess seams and two-piece sleeve.
After the first fitting, I realized that the "boxiness" of this pattern does not suit my body shape. So I proceeded with my usual alterations: a sway back adjustment and more rounded shoulders. I ended up creating a princess seam and adding little darts on the shoulders. I also thought that adding a bit of length will look more flattering on me.
On the front, I also added my usual SBA by creating an additional dart which I will combine with the one which existed on the original pattern to create one bigger dart.
After I marked all necessary alterations with a soft-tip pen, this is what I have.
To transfer my alternations to the pattern pieces, I ripped my muslin apart and overlaid each piece requiring an alteration with the paper pattern. Then, using a tracing wheel with metal points (it's called "roulette" in Japanese but I've no idea about it's official name in English), I marked new lines onto the pattern.
My absolutely favorite tracing tool!
In the case with the second dart, I proceeded slightly differently: I did not trace it but added it to the original dart. Because there was some fabric separating two darts, I measured the width of the new dart and added this exact width to the old one.
Here is a picture of a brand new pattern piece. I won't go into details about this particular pattern piece now, but if you are interested I can create a separate post explaining how I created a princess seam on the back.
And after three hours working on my princess seam and re-drafting the sleeves, the end result looks fine in my eyes. I have a little doubt about two areas of my jacket now: the sleeves' width and this little area circled in the photo below. But fear not, we will go for the second fitting once our jacket is cut from the real fabric and basted. Because, of course, the tweed and wool used for the jacket behave completely different from the muslin fabric.
Would you like to share with us your alterations? If you have questions, feel free to post your photos to our Flickr group and we will all try to help you!
Thanks for the step-by-step on day one of the Little French Jacket sewalong! I, too, am enrolled Susan's Craftsy class, and I know it will be invaluable!
Thanks for the great instructions for fitting the muslin! My pcs are cut but will require lots of tweaking before it fits me.
Oh wow. I'm not doing the jacket (sorry) but these are really useful. Thanks for documenting them so clearly and being so thorough in your instructions. I have an awesome knit blazer pattern from Knipmode that needs fixing up and this is exactly the incentive I need to get on with it. Cheers.
Are these dead darts? I'm curious as to why you selected this pattern which necessitated adding princess seams in the back and darts. Also, are you using a 2-piece sleeve rather than a 3-piece one? Interesting different method on the muslin -- but I'm really partial to my thread basted lines! Gives me something to hold on to!
I am divided as to whether I want to use my TNT french jacket pattern (which went through a muslin process to get where it is) or try a new one. I like both StyleArc patterns, I have the newer Claire Shaeffer Vogue, and a variety of other Chanel-ish patterns. What I like about the pattern I have already adjusted to fit is that it has shoulder princess seams rather than armscye princess seams. This seems easier to adjust from my narrow shoulders to the bust and back to the waist without having a lot of extra fabric pouffing out here and there.
Thanks for the kick start Inna! Yes, I too enrolled last week for Susan's Craftsy course and although I've only watched a few 'episodes', there is a lot of detail in them. SO I just wanted to say well done on this post. I can't imagine how difficult it must be to get enough detail but not overload. Cheers!
Susan's class is the best! I go back to it on a weekly basis: you always find there something new!
I covered only my personal adjustments since this post would last forever. Good luck with your muslin!
So I chose this pattern because I thought that this jacket would look nice on me even though I knew that my back is not great for this shape. I think we all go through this mistake from time to time: smitten by a pattern we don't pay much attention to whether it would fit our body shapes. Let's say, I wanted to fool myself but the muslin proved me wrong.
And not, these are not dead darts but regular darts because I use them to accommodate curved areas of my body (sway back and rounded shoulders). Dead darts are usually smaller and are located of flat areas. Sorry if it was not too clear from the explanations.
The pattern is a two-piece sleeve.
Oh, Susan's class is my go-to resource whenever I have doubts. Both watching videos or reading comments bring incredible amount of useful sewing info! I can't wait to get hold on Susan's Jacket DVDs!
Putting together the sew-along resulted to be quite challenging! It's always a compromise between the length of each post and the level of details.. Phew! If you want to provide me with more feedback about the sew-along, please don't hesitate!
WOW You did an awesome work with the muslin! I´m not doing the sew-along but I´m going to follow all the steps!
I've been eagerly awaiting this post! I have just been tracing my pattern and I'm wondering about the seam allowances. When you say large, what sort of size do you mean? Is 2cm enough for the seam allowances with about 5cm added to the hem and cuffs, or would you add more? Thanks for the very informative first post, can't wait to get cracking on the muslin.
Yea Knip do have a lot of different stuff don't they?
You should try that pattern if you've got the time, it would be interesting to know what their pdf patterns are like. Check if they've got a copyshop version i.e. no cutting and pasting of ruddy A4s.. The printer I use out here has a large format printer and prints on Swedish tissue...♥ Actually I should blog about it-he totally deserves the coverage.
The Knip block's got a bit more ease and height i.e. meant for taller people with an active lifestyle (which I imagine all Dutch people enjoy.. XD). Needs a pinch taken out of shoulder width (to get the shoulder point correct) and a couple of cm of heightremoved at the waist.. Will be interesting to see how you go.
Thanks for the post. I"m looking forward to this sew-a-long. I'm going to work up the Style Arc 'Coco' pattern. Just need to find two coordinating fabrics to work with. Wish me luck.
The sleeve conversion was not really planned for this sew-along...But let me talk with Leisa. Fitting sleeves is not only the least favourite thing (for all of us) but is the most annoying! For this reason we will allow two weeks for setting the sleeves. Good luck with your muslin!
Hi Inna, thanks for the post. I'm making a muslin of V7975 but would prefer a V-shape neckline. Will altering my neckline mean looking for trouble? No facings, no interfacing, risk of distortion? You're an expert on this issue. Was it complicated to get the neckline right on your yellow jacket?
Thank you Maider! I am sure you can pick up some elements of our sew-along which are possible to incorporate into other projects! Hopefully, it will be helpful for people who don't participate :) But, hey, you are working on a hell of a jacket!
Good luck, Debbie! ( ͡° ͜ʖ ͡°) I am sure you'll find some beautiful fabric in no time! As we sew along, I'd like to hear more about your Style Arc's patter because I was keeping it on the top of my list.
V7975 is a great pattern! Not to worry about the neckline at all! For the LFJ there is no facing, no interfacing but the risk of distortion is pretty low, unless you pull the fabric with all of your forces imagining that this is your manager •‿•) Believe me, the neckline is the least complicated part. But in case you are not completely sure about the neckline shape don't forget to keep really really large seam allowances: it's always easier to go from the standard neckline to a V-shape then the other way around.
In our case 2-3cm seam allowances are enough. Use the knowledge of your body and your usual adjustments. If you know that a certain area is tricky (for example, armscye or shoulers, allow slightly bigger seam allowance). In the worst scenario, you can either re-cut a new piece or add a little piece of muslin where necesary.
For the hem and cuffs on a muslin, I usually do not add any seam allowances but cut at the seam lines. But this is just my personal preference.
We will work with really large seam allowances for the fashion fabric (5-6cm depending on how much does your fabric fray). But this is our next topic which will be covered by Leisa next week!
Claire Shaeffer's DVD Couture Techniques Workshop Basics explains how to thread trace. When done, you can easily tell the right side from the wrong side. She does recommend marking the top of each piece. It's really expensive on Amazon for some reason right now, but you can buy it form another source like overstock.com or half.com. The new edition of her book, Couture Sewing,, is also very helpful. And of course, she just came out with a book and DVD on sewing a Chanel-style jacket, which are excellent: Couture Sewing: The Couture Cardigan Jacket, Sewing Secrets from a Chanel Collector.
Susan Khalje's The Couture Dress course is quite good, but I don't like being dependent on access to Craftsy.
This is really useful. I'm still fairly new to pattern cutting and fitting concepts as I've only started dresses recently. I guess the constructive comment I can add to this post is that I've purchased the craftsy class "Sew the perfect fit" and found it helpful. The approach is a bit different apparently as it consists in cutting the muslin in strategic places and then either reduce the size of the muslin or insert extra fabric where needed. I have not practiced it yet but let's say it makes sense and the course covers top and bottom including various body shapes.
Claire's book is is super interesting and useful but unfortunately I an unfamiliar with her DVD lesson. I use Macbook Air, which does not have a DVD port, and I prefer to store my information in the cloud and access it through Internet, hence my inclination toward services like Craftsy. But I think it's great that today we can choose the way we consume information!
When you talk about thread tracing, is it related to the muslin? Is this the similar technique that I've described in the post? I would like to get hold of her book once it's available on sale where I live and to see the detailed photos of jackets. Exciting!
Yes, thread tracing is the distinctive stitch used to mark the muslin and later, the actual fabric. It's a form uneven basting and creates a distinctive look on each side. Shaeffer explains how to mark seams and intersections.
I understand why you prefer the Cloud. The DVD Basics workshop, however, is great for people with DVD readers because it illustrates many little issues that don't get explained elsewhere.
I haven't had a chance to play the DVD that goes with Chanel-style jacket book, but the book is really good. Her book is available on Amazon.com. Is the shipping really expensive to Japan?
I will get started next week! How long is your shoulder dart? Is it perpendicular to the shoulder?
It's not 100% perpendicular. I just pinched in a few areas to see where it hides my "wings". I would not worry too much about the exact dart placement for couple of reasons: tweed or bouclé are not as sturdy as cotton or wool and any little imperfection won't show but also the jacket is usually worn opened, so there will be lots of movement for somebody to catch the sight of it.
This needle point tracing wheel looks pretty aggressive :) Is it for working with leather?
People with cloud are so dependent on a good Internet connection if any! If I lived in a remote area with a dial-up Internet I think I would value DVD or any other hard copy sources more, for sure!
Amazon.com does ship to Japan and the cost is acceptable. But within three weeks I will move to London where this book is still not on sale. It does not make sense for me to order the book now and add more weight to my already over oversized luggage (•ิ_•ิ)? So have to wait !
Thanks for your feedback on "Sew the Perfect Fit". Again, it's a good thing to know a few different ways of working with a muslin or pattern and use the one which works best for you. I also find my fitting techniques considerably improved when fitting clothes on other people.
method. I have never tried the method with basting but will try it.
I have just found this sewalong and really want to join in. I have made V7975 up before in a Chanel style but there definitely isn't any hand sewing or quilting in that one. I also have another version of V7975 on the table that is true to the little french jacket (it has quilting, a lot of handsewing etc) but after reading everyone's comments, the blog posts and the silk tweed mix that followed me home the other week, I want to do this. Seeing I have already had my jacket fitted for me, I won't do the muslin and will wait for the next lot of instructions. One question though, I can't find any mention, do we pre-treat our fabric?
Hi Sharon! I am very excited to see you join it :) There are never enough of French jackets, aren't they? Next week Leisa will talk about cutting the fashion fabric and will cover the question you asked. In my case, I don't do anything crazy with my wool/tweed: no London shrink, no dry cleaning, no washing. I just steam my fabric with an iron once or twice. Same goes for chêpe-de-Chine. I never had problems with any garments post-washing or dry-cleaning.
Jenny, Emily and I spent this last Saturday at mine doing draped pants blocks from the Duburg book. I'll prob be doing one for Maria (velosewer) when she gets here next month 'cuz we got a sleepover scheduled XD OMG so glad I started blogging about sewing-cool people everywhere.
Just link to a pre-existing tutorial or scan a book page under 'fair-use'. Don't spend a lot of time on things that everyone ain't doing. Just ma two cents.
Cool-so does that cover fitting menswear as well as women's wear? Or are there just suggestions that would work irrespective of the style?
the class covers all the basics about women's wear, nothing about men's wear I'm afraid!
I admire you and Leisa to take the effort to share your learning with all of us. The LFJ is the most versatile jacket I have ever made. Since March 2012, my class with Susan, I am now finishing my 6th jacket. Having read your blog I wonder why you choose the pattern with the classic princess line. If you look at the Vogue 7975 pattern the princess seams are moved to the shoulder, which has two advantages: you can incorporate the back and front dart in this seam and the quilting is easier with the straighter lines. I also have rounded shoulder blades and prefer a more fitted style and that is perfectly possible when you move the seams to the shoulder. I must say I have not read all the comments, so maybe you have already answered this question.
Seam allowances? ? 5/8" hangover. Going to work at this till it's like I've never heard of 5/8"
Well, we work with stitching lines for more precision and better fit. Try this out! You'll love it!


Going somewhere tropical!? The MINKPINK Tropics Paperbag shorts are the perfect shorts to travel in! The high-waisted paperbag shorts features paperbag style waist with removable tie belt, front pockets and tropical floral print allover. Style this with our MINKPINK Tropics Bandeau Top for a complete set!


Article in Indian journal of environmental health 43(4):169-73 · November 2001 with 374 ... Stone crushers are small scale industries in the unorganised sector.
mining and minerals companies india; Mobile crushers have been impact of mining work environment impact statement and an environment stone crusher.
Feb 14, 2016 ... how much cost of stone crusher small scale machine in india used ... of stone crusher industry in india history of stone crusher, SBM Mining .
The stone crushing industry at Lalpahari include two main operations: (1) ... and (2) crushing operations (hammering of bigger chunks of stones into smaller pieces ... Forest at Tumboni Beat, Rampurhat) in Birbhum District, West Bengal, India.
6 days ago ... small stone jaw crusher hot sell in india and bangladesh ... Rock Crusher, mining industry various,such as jaw crusher, price in india; small .
Get Details of Stone Crushing Industries. ... RANCHI - 843003, INDIA. Manufacturers & Suppliers of Stone Crushing Plant, Jaw Crusher. Send Enquiry.
Introduction. Stone crushing in India is basically a labor intensive small scale. industry, where most of the operations are performed manually. Aslam et al.
India, the Stone Crushing Industry sector is estimated to have an annual .... In these types of small stone crushers, the mined raw stones are transported to.
stone crusher india industry - gvnpolytechniccoin Jan 25, 2012 stone crushing industry in India Stone ... Stone Crusher Price in India, Small Cone Crusher Plant ,.


LEWIS HAMILTON WINS F1 ABU DHABI GRAND PRIX; BUTTON FINISHES 3RD ON ENKEI WHEELS!
LEWIS HAMILTON TAKES 2ND AT F1 KOREAN GRAND PRIX ON ENKEI WHEELS!
Congratulations to Lewis Hamilton for winning 2nd place at the F1 Korean Grand prix! Enkei Wheels is the official wheel supplier to the F1 Vodafone McLaren Mercedes team!
BUTTON WINS F1 JAPANESE GRAND PRIX!
NEWS: BUTTON WINS FORMULA 1 HUNGARY GRAND PRIX!


(St. Petersburg, Florida – September 14, 2012) –The Learning Systems Group of Freedom Scientific, Inc., developer of literacy software designed to create custom learning environments for struggling students, announced today the release of the newest version of the industry-leading WYNN™ software. WYNN 7.0 adds PAL (Promoting Academic Literacy) features that were partly funded by a Steppingstones of Technology Innovation for Children with Disabilities grant awarded by the US Department of Education's Office of Special Education Programs (OSEP). The grant was awarded in partnership with Dr. Cynthia Okolo, an educational researcher at Michigan State University.
WYNN 7 includes the PREPARE process, a well-researched and systematic educational process to support active interaction with text, including supports for reading, writing, studying, and organizing notes. The PREPARE process paired with the PAL features provides a powerful support structure for all students. The PAL features include electronic notecards and writing templates.
WYNN 7.0, building on its well-recognized educational, features, is the only software that offers struggling students "electronic notecards" and WebMasking™. "Our electronic notecards provide unparalleled support to students for better comprehension and to support writing. Deep conceptual learning, rather than rote learning, is the goal of this product," said Roberta Brosnahan, VP & General Manager of the Learning Systems Group. She continued, "The PREPARE process, coupled with WYNN 7 features, provides an engaging, interactive approach to successful learning.
WYNN's unique features and benefits were created with input from educators, researchers, and individuals with learning difficulties such as dyslexia. It uses Universal Design for Learning (UDL) principles to enhance success and was designed to be useful for all users, yet excels at satisfying the needs of learning disabled and struggling students.
WYNN continues to maintain other unique differentiators for the benefit of all users, such as: its clean, exceptionally easy-to-use user interface; Text View/Exact View method to display documents; Web Browsing features, including the patented WebMasking® feature; NavBar for managing open documents; and visual tailoring, including the ability to change size, line spacing, and word spacing with a click of the mouse. WYNN 7 also supports the 2-½ pound PEARL® document camera, providing fast and portable scanning and reading. WYNN's benefits help students and adults lead more productive lives, whether it is in the classroom, at home, or on the job.
For a WYNN 7.0 demo disk and pricing information, contact Freedom Scientific's Learning Systems Group by phone at (800) 444-4443 or by e-mail at WYNN at FreedomScientific.com. You can also download the demo version at our Web site at http://www.freedomscientific.com/lsg/products/demos.asp.
Freedom Scientific is the leading worldwide provider of assistive technology products for those with vision impairments. The Company sells its products worldwide and has offices in Florida and Switzerland. The Company's products have been translated into 24 languages and are available in 55 countries. Freedom also has a line of software products for those with learning disabilities.
Freedom Scientific's Learning Systems Group is recognized as a leading provider of easy-to-use, easy-to-learn solutions, based on sound educational principles. The products assist individuals of all ages to be more successful with reading and writing. Visit www.freedomscientific.com/lsg.
Freedom Scientific®, WYNN™, and PEARL® are either trademarks or registered trademarks in the United States and/or other countries. The names of actual companies and products mentioned herein may be the trademarks of their respective owners.
The contents of this software program were developed under a grant from the US Department of Education, #H327A090045. However, those contents do not necessarily represent the policy of the US Department of Education, and you should not assume endorsement by the Federal Government.
or e-mail wynn at freedomscientific.com.


Signing Sandy can be yours! Little figurative 35cm living puppet (Emil) from the Puppet Company. He is fully clothed and dungarees and shoes can be removed. Working mouth & glove type hand operation, perfect for little hands.


text:
Q: How to find words with only/more specified letters using preg_grep in array? I have sample function for searching words from array with specified letters:
public static function getWords($words, $specifed_letters)
{
    $pattern = is_array($specifed_letters) ? '/[' . implode("",
    $specifed_letters) . ']/u' : '/[' .$specifed_letters. ']/u';
    $result = preg_grep($pattern, $array_words);
    return $result;
}

Example usage:
$words = ["apple", "sample", "app", "тоҷик", "отабек", "баҳодурбек"];
$result = getWords($words, $letters = ['l', 's']);

This example will return words: apple, sample.
Because in this words have letters "l" or "s".
How I can search words where have all specifed letters in word?
For example if I add to specifed letters "app" then from words array must be return words: app, apple.
And how search word with only specifed letters. For example I will write word "app" in shuffled variant "pap". And how I can get on result only word "app" without "apple"?

A: You could split the word characters to an array and loop them, and split the characters from the specified string to an array.
If one of the word characters occur in the characters from the specified string array, remove the character from both arrays.
Once the loop is done, verify that there are no more characters left in the characters from the specified string array.
$words = ["apple", "sample", "app", "justappgg", "тоҷик", "отабек", "баҳодурбек", "APELCIN", "API", "pap"];
mb_internal_encoding("UTF-8");

foreach ($words as $word) {
    $wordSplit = preg_split('//u', $word, null, PREG_SPLIT_NO_EMPTY);
    $strSplit = preg_split('//u', $str, null, PREG_SPLIT_NO_EMPTY);
    $wordSplit = array_filter($wordSplit, function ($x) use (&$strSplit) {
        if (in_array(strtolower($x), array_map('strtolower', $strSplit), true)) {
            $pos = array_search(strtolower($x), array_map('strtolower', $strSplit), true);
            unset($strSplit[$pos]);
            return false;
        }
        return true;
    });
    if (count($strSplit) === 0) {
        echo "$word contains all letters of $str" . PHP_EOL;
    }
}

Demo

A: You can use preg_grep.
If you implode the letters inside [] in the regex pattern it should look for the letter and return the item if found.
$words = ["apple", "sample", "app", "тоҷик", "отабек", "баҳодурбек"];
$letters = ['l', 's'];

$res = preg_grep("/[" . implode("", $letters) . "]/", $words); // pattern = "/[ls]/"
var_dump($res);

https://3v4l.org/UZTYZ
EDIT
But this part of your question: And how search word with only specifed letters. For example I will write word "app" in shuffled variant "pap". And how I can get on result only word "app" without "apple"?
Is the exact opposite of the first part where you wanted a very loose search.
Are you expecting one loose and one exact result array?

You can do the exact match by splitting the strings and sorting the letters (in the array).
Then check if the arrays match each other. If they do, then it's an exact match.
$words = ["apple", "sample", "app", "тоҷик", "отабек", "баҳодурбек"];
$find = "pap";

$find = str_split($find);
sort($find);
foreach($words as $word){
    $temp = str_split($word);
    sort($temp);
    if($temp == $find){
        echo "match " . $word . "\n";
    }
}

https://3v4l.org/WbTUK

redpajama_set_name: RedPajamaStackExchange


text:
STREAMING NOW: Watch Now
Teal Chair makes debut in Boise
If you limited time to live what would you do? Students at Eagle High School are asking this question with their film...
Updated: Apr 28, 2018 12:04 PM
If you limited time to live what would you do? Students at Eagle High School are asking this question with their film the Teal Chair. This question has folks talking. What started off as a school project has turned into a topic people can't seem to get off their minds.
Back in October leadership at Treasure Valley Hospice approached the Eagle High School broadcasting department asking for their help with a project. The goal was to get people talking about living instead of dying.
"We had no idea that this project would grow the legs that it has grown, that we would go to the sun valley film festival, that senators would be interested in the project," said Honey Goodman, Co-owner of the Treasure Valley Hospice.
The film made its public debut Thursday night at Jump. About 500 people packed the room just to get a glimpse of the 30 -minute documentary. The film has also been nominated for a category in the 2018 sun valley film festival.Student filmmaker Aiden Holcroft says the short film took about three months to bring to life.
"It's been surreal because as a high schooler I am not associated with the thought of death and dying very often. I think its been eye-opening in ways that I could never have imagined where I am dealing with people that are experiencing a lot of life, " said Holcroft.
The students believe they have answered the question to life.
"Relationships with people are the most important thing that should be in your life. You should be focusing on the material goods or just your job," said Holdcroft.
If you would like to view the film, you can do so by reaching out to the Treasure Valley Hospice.
Peek inside Boise, Idaho's vibrant Basque community
St. Mary's to evict disgraced Boise priest
An American Ninja Warrior shows off Boise
Boise Police Investigating Stabbing on State Street
Prosecutor weighing death penalty in Boise attack
Wizard World Comic Con hits downtown Boise
More than 100 goats invade Boise neighborhood
Kraft is making its Super Bowl debut
Three baby goats make their debut zoo
Rain moves back into out area overnight
Tupelo motorcade symbol of Martin Luther King Jr.'s dream
VIDEO: MLK Holiday Committee hosts food drive in partnership with West Point church


Bureau of Ocean Energy Management (2016-2019), "Assessment of Ship Shoal Borrow Areas for Coastal Restoration of Louisiana Barrier Islands", PI, Xu, K.H., Co-PI, Bentley, S., Li, C, Shaw, R.
Louisiana Board of Regents, Traditional Enhancement Program (2016-2017), "Acquisition of Acoustic and Optical Sensors to Enhance the Research and Teaching of Sediment Diversion and Coastal Restoration", PI, Xu, K.H.
Louisiana Sea Grant, (2016-2018), "From Physics to Oysters: An Integrated Modeling Study of the Potential Impacts of Future Large Sediment Diversions on Louisiana Eastern Oyster". PI, Huang, H., Co-PI, Justic, D., Xu, K.H., LaPeyre, M., LaPeyre, J.
Bureau of Ocean Energy Management, (2015-2018), "Investigation of an Ancient Bald Cypress Forest in the Northern Gulf of Mexico, U.S.A.",PI, DeLong, K., Co-PI, Harley, G., Bentley, S., Xu, K.H., Reese, C.
Bureau of Ocean Energy Management (2014-2017), "Assessment of Mud-Capped Dredge Pit Evolution on the Outer Continental Shelf of northern Gulf of Mexico", PI, Xu, K.H., Co-PI, Bentley, S., Li, C.
National Science Foundation and the Louisiana Board of Regents, EPSCoR Pfund Program (2014-2015), "A Study of Sediment-Plant Interaction to Benefit Coastal Protection and Restoration",PI, Xu, K.H.
The Water Institute of Gulf (2014-2015), "Geological and Geotechnical Characterization of Middle Barataria Bay and Middle Breton Sound Diversion Receiving Basins",PI, Bentley, S., Co-PI, Xu, K.H., Chen, Q.
The Water Institute of Gulf (2013-2014), "Geological and Geotechnical Characterization of Lower Barataria Bay and Lower Breton Sound Diversion Receiving Basins", PI, Bentley, S., Co-PI, Xu, K.H., Chen, Q.


text:
PM Meets With Indian External Affairs Ministry
Tuesday February 24th, 2015 by Tishreen (Pro-government newspaper)
Syrian prime minister meets with Indian delegation to discuss reconstruction through investment and development projects
Prime Minister Wael al-Halki met the head of the West Asia and North Africa department at the Indian External Affairs Ministry, Joint Secretary Sandeep Kumar, on Monday.
During the meeting, Premier Halki affirmed the government's desire to expand economic and industrial cooperation with friendly countries like India, calling on Indian businessmen and companies to carry out investment, development, and services projects in Syria, and to take part in the upcoming reconstruction stage – citing significant cooperation prospects in the fields of food and consumer products, pharmaceuticals, and equipping factories, hospitals, and power stations.
The PM stressed the need for all countries to cooperate with Syria to combat terrorism, reigning in states that provide financial, military, and logistics support to terrorism.
Kumar asserted the Indian government's commitment to expanding cooperation with Syria, helping alleviate the suffering of the Syrian people, and providing the needs to confront terrorism.
The two representatives discussed means to boost cooperation and realize agreements, in addition to the prospect of signing new pacts and cooperating in the fields of electricity, pharmaceuticals, transport, agriculture, petroleum, gas, development and services projects.
Deputy Prime Minister Walid al-Muallem discussed with Kumar and the accompanying delegation bilateral relations and ways to boost productivity in all fields, with the minister briefing the Indian delegation on methodical terrorism targeting Syria.
Muallem stressed the need to unite regional and international efforts to preserve international peace and security and to respect the Security Council's resolution on combating terrorism and drying up its sources.
Kumar said that India is opposed to internal interference in countries' affairs, and that it believes that terrorism has become a concern for many states, which requires the rallying of international efforts to combat it.
He also affirmed India's support for a political solution in Syria which would alleviate the suffering of the Syrian people, leading to stability in Syria and the region.


In her time, Gertrude Stein was a high-profile writer and patron of the arts, known for writ-ing enigmatic lines like "Rose is a rose is a rose is a rose," and for coining the term the Lost Generation to describe people who came of age during World War I. But today she's probably most famous for the Paris salon she hosted in the years after the war, attracting Modernist luminaries like Pablo Picasso, Ernest Hemingway, F. Scott Fitzgerald, and Henri Matisse.
The Renwick Hotel in New York City has sought to recapture her spirit with the 10th-floor Gertrude Stein Suite — the latest in a series of rooms celebrating writers who spent time at the Midtown Manhattan property, including Fitzgerald, John Steinbeck, and Thomas Mann. Stein's suite features a variety of nods to her life and work, including a shelf of her novels, vintage French milk bottles, a recreation of Picasso's portrait of Stein, and an infinite loop of "Rose is a rose" rendered on one wall.


text:
31 Days to Scare ~ Death of Me
by Joe Movie Review	• Tags: Alex Essoe, Ari Margolis, Darren Lynn Bousman, David Tish, Death of Me, James Morley III, Kat Ingkarat, Kelly B. Jones, Luke Hemsworth, Maggie Q, Saban Films
Available In Theatres, On Demand and Digital on 10/2
Synopsis: A vacationing couple must unravel the mystery behind a strange video that shows one of them killing the other.
Stars: Maggie Q, Luke Hemsworth, Alex Essoe, Kat Ingkarat, Kelly B. Jones
Director: Darren Lynn Bousman
Running Length: 94 minutes
TMMM Score: (4.5/10)
Review: My goodness, doesn't the poster for Death of Me promise something just absolutely terrifying? It's one of those arresting images that instantly catches your eye and, like a juicy steak cooking on a grill that has made many a cartoon dog float across a yard in ecstasy once he gets a whiff, it's meant to attract horror hounds who happily chow down on tasty treats such as this. The trouble is, the poster is by far the best thing about this new frightener which squanders a perfect locale and good-looking cast in favor of a recycled plot, substandard scares, and a general lack of energy that does more to kill the mood than anything supernatural.
The last morning of a vacation is always rough but for married couple Neil and Christine it's particularly head spinning. Their room is a tangled mess, Christine (Maggie Q, Allegiant) is covered with some strange substance and Neil is disoriented to the point where he's no help at all. Scrambling to meet their ferry, they are unable to board without their passports which have gone missing. Back at their vacation rental and backtracking their steps to find their missing documents, they begin to put the pieces back together and remember the night before. Both eventually recall a strange encounter with a waitress at a local watering hole who gave Christine a drink and a charm she now wears around her neck. That's pretty much all they remember…so it's a good thing Neil (Luke Hemsworth, Thor: Ragnarok, no, not that Hemsworth. No, not that one…yes, that's the one) has a lengthy video on his phone they can watch.
What they see on his phone can't be true because it ends with Christine dead and buried six feet under the ground. Yet, come to think of it, that might explain a lot about the state both were in when they woke up earlier that morning. Shrugging off this impossibility quite quickly (not to mention the distressing suggestion Luke, y'know, murdered his wife and buried her and now doesn't remember it) the make contact with their host (Alex Essoe, Homewrecker) who is friendly enough (or IS she?) and lets them stay on another day or so while they figure out what's happening and why Christine can't seem to take off her new necklace without looking….well, dead. It doesn't take a genius to figure out what's transpiring and the script, credited to a whopping THREE screenwriters, eventually doesn't bother with coherence as characters change motivations and nightmares become reality which are really dreams but wait are they real? Everything seems to be made up as it goes along, which makes the whole thing feel flimsy.
Director Darren Lynn Bousman was behind the camera for three of the Saw films and also directed the twisted musical Repo! The Genetic Opera as well as one of the segments of the fun anthology Tales of Halloween but something is missing the execution here. Much of it has to be attributed to the script which just isn't that special and therefore creaks through the motions toward an ending that you're likely able to suss out before the film is half over. I also wish the leads had a bit more of an edge to them. The least known Hemsworth brother, Luke is mostly cardboard and forgettable as is, regrettably, Maggie Q doing most of the heavy lifting as Christine. Maggie Q is always someone I'm rooting for to be better than the material she's given, to find a way to rise above it…but it just doesn't stick.
I can see this one being a small diversion for folks looking for a well-produced horror film this Halloween season. The Thailand setting is nice, even if it doesn't paint the island or the locals in any kind of positive light, and when it does manage to drum up some suspense by instilling some gross-out gore, it's handled with some measure of sick charm. Still, we're at the point where audiences know you can do a lot with a little if you have the right elements and Death of Me is lacking in several key areas to make it come alive.
Movie Review ~ The Devil to Pay
31 Days to Scare ~ Monsterland
One comment on "31 Days to Scare ~ Death of Me"
The Alliance Lately: Issue No. 12 – The Minnesota Film Critics Alliance says:
[…] Halloween, Scooby-Doo," "A Howling in the Woods," " Monsterland," "Death of Me," "The Lie," "Black Box" and "Possessor" for his 31 Days to Scare […]


text:
'The Last Four Days of Paddy Buckley'
Review by Shirley Shiffler
"If there was a running motif throughout my brief life, it would be the close and present nature of death. I'd known it intimately from the start." So begins the last day in the life of funeral home employee Paddy Buckley. His mother died when he was 4, his father when he was 33, and his wife and unborn daughter two years ago. When the story begins, Paddy has no idea his end is so near.
By Jeremy Massey
Three days earlier was quite a day for Paddy, a caring and upright young man. First, he visits a lovely widow to arrange her husband's funeral, but after consoling her, it turns out he will instead need to work with their even lovelier daughter on the arrangements for a double funeral. Later, one of his colleagues comes to him in a panic after the wrong body is delivered from a mortuary in London, and Paddy is led to deceive that family to avoid having an open casket funeral. Then he is called out in the middle of the night to attend to a death in a nursing home. While driving home from that call at 3 a.m. in the rain, he accidentally hits a man. When Paddy gets out to check, he realizes that he has killed the brother of Dublin's most notorious crime boss, Vincent Cullen. Worst of all, Paddy knows that if Cullen finds out, he'll have Paddy killed. And as you can probably tell from the title, Cullen does indeed find out.
Jeremy Massey has drawn from his experience as a third-generation undertaker to write an edgy, sometimes violent and darkly comic thriller that I couldn't put down. CV
Shirley Shiffler grew up in Urbandale, graduated from Drake (twice!), and lives in Beaverdale.


Home / Leica Zoom eyepiece 25-50 x WW ASPH.
The APO-Televid Aspherical eyepiece boasts optical superiority and durability with its wide angle 60 degree field of view, fully multi-coated lens system, rapid interchange bayonet attachment method, rubberized function elements and twist out eye cup. The nitrogen filled eye piece is completely fog/shockproof. Designed to fit the APO-Televid Spotting Scope Body.


text:
package kafka.log

import java.io.{DataOutputStream, File}
import java.nio._
import java.util.Date
import java.util.concurrent.{CountDownLatch, TimeUnit}

import com.yammer.metrics.core.Gauge
import kafka.common._
import kafka.message._
import kafka.metrics.KafkaMetricsGroup
import kafka.utils._

import scala.Iterable
import scala.collection._

/**
 * The cleaner is responsible for removing obsolete records from logs which have the dedupe retention strategy.
 * A message with key K and offset O is obsolete if there exists a message with key K and offset O' such that O < O'.
 *
 * Each log can be thought of being split into two sections of segments: a "clean" section which has previously been cleaned followed by a
 * "dirty" section that has not yet been cleaned. The dirty section is further divided into the "cleanable" section followed by an "uncleanable" section.
 * The uncleanable section is excluded from cleaning. The active log segment is always uncleanable. If there is a
 * compaction lag time set, segments whose largest message timestamp is within the compaction lag time of the cleaning operation are also uncleanable.
 *
 * The cleaning is carried out by a pool of background threads. Each thread chooses the dirtiest log that has the "dedupe" retention policy
 * and cleans that. The dirtiness of the log is guessed by taking the ratio of bytes in the dirty section of the log to the total bytes in the log.
 *
 * To clean a log the cleaner first builds a mapping of key=>last_offset for the dirty section of the log. See kafka.log.OffsetMap for details of
 * the implementation of the mapping.
 *
 * Once the key=>offset map is built, the log is cleaned by recopying each log segment but omitting any key that appears in the offset map with a
 * higher offset than what is found in the segment (i.e. messages with a key that appears in the dirty section of the log).
 *
 * To avoid segments shrinking to very small sizes with repeated cleanings we implement a rule by which if we will merge successive segments when
 * doing a cleaning if their log and index size are less than the maximum log and index size prior to the clean beginning.
 *
 * Cleaned segments are swapped into the log as they become available.
 *
 * One nuance that the cleaner must handle is log truncation. If a log is truncated while it is being cleaned the cleaning of that log is aborted.
 *
 * Messages with null payload are treated as deletes for the purpose of log compaction. This means that they receive special treatment by the cleaner.
 * The cleaner will only retain delete records for a period of time to avoid accumulating space indefinitely. This period of time is configurable on a per-topic
 * basis and is measured from the time the segment enters the clean portion of the log (at which point any prior message with that key has been removed).
 * Delete markers in the clean section of the log that are older than this time will not be retained when log segments are being recopied as part of cleaning.
 *
 * @param config Configuration parameters for the cleaner
 * @param logDirs The directories where offset checkpoints reside
 * @param logs The pool of logs
 * @param time A way to control the passage of time
 */
class LogCleaner(val config: CleanerConfig,
                 val logDirs: Array[File],
                 val logs: Pool[TopicAndPartition, Log],
                 time: Time = SystemTime) extends Logging with KafkaMetricsGroup {

  /* for managing the state of partitions being cleaned. package-private to allow access in tests */
  private[log] val cleanerManager = new LogCleanerManager(logDirs, logs)

  /* a throttle used to limit the I/O of all the cleaner threads to a user-specified maximum rate */
  private val throttler = new Throttler(desiredRatePerSec = config.maxIoBytesPerSecond,
                                        checkIntervalMs = 300,
                                        throttleDown = true,
                                        "cleaner-io",
                                        "bytes",
                                        time = time)

  /* the threads */
  private val cleaners = (0 until config.numThreads).map(new CleanerThread(_))

  /* a metric to track the maximum utilization of any thread's buffer in the last cleaning */
  newGauge("max-buffer-utilization-percent",
           new Gauge[Int] {
             def value: Int = cleaners.map(_.lastStats).map(100 * _.bufferUtilization).max.toInt
           })
  /* a metric to track the recopy rate of each thread's last cleaning */
  newGauge("cleaner-recopy-percent",
           new Gauge[Int] {
             def value: Int = {
               val stats = cleaners.map(_.lastStats)
               val recopyRate = stats.map(_.bytesWritten).sum.toDouble / math.max(stats.map(_.bytesRead).sum, 1)
               (100 * recopyRate).toInt
             }
           })
  /* a metric to track the maximum cleaning time for the last cleaning from each thread */
  newGauge("max-clean-time-secs",
           new Gauge[Int] {
             def value: Int = cleaners.map(_.lastStats).map(_.elapsedSecs).max.toInt
           })

  /**
   * Start the background cleaning
   */
  def startup() {
    info("Starting the log cleaner")
    cleaners.foreach(_.start())
  }

  /**
   * Stop the background cleaning
   */
  def shutdown() {
    info("Shutting down the log cleaner.")
    cleaners.foreach(_.shutdown())
  }

  /**
   *  Abort the cleaning of a particular partition, if it's in progress. This call blocks until the cleaning of
   *  the partition is aborted.
   */
  def abortCleaning(topicAndPartition: TopicAndPartition) {
    cleanerManager.abortCleaning(topicAndPartition)
  }

  /**
   * Update checkpoint file, removing topics and partitions that no longer exist
   */
  def updateCheckpoints(dataDir: File) {
    cleanerManager.updateCheckpoints(dataDir, update=None)
  }

  /**
   * Truncate cleaner offset checkpoint for the given partition if its checkpointed offset is larger than the given offset
   */
  def maybeTruncateCheckpoint(dataDir: File, topicAndPartition: TopicAndPartition, offset: Long) {
    cleanerManager.maybeTruncateCheckpoint(dataDir, topicAndPartition, offset)
  }

  /**
   *  Abort the cleaning of a particular partition if it's in progress, and pause any future cleaning of this partition.
   *  This call blocks until the cleaning of the partition is aborted and paused.
   */
  def abortAndPauseCleaning(topicAndPartition: TopicAndPartition) {
    cleanerManager.abortAndPauseCleaning(topicAndPartition)
  }

  /**
   *  Resume the cleaning of a paused partition. This call blocks until the cleaning of a partition is resumed.
   */
  def resumeCleaning(topicAndPartition: TopicAndPartition) {
    cleanerManager.resumeCleaning(topicAndPartition)
  }

  /**
   * For testing, a way to know when work has completed. This method waits until the
   * cleaner has processed up to the given offset on the specified topic/partition
   *
   * @param topic The Topic to be cleaned
   * @param part The partition of the topic to be cleaned
   * @param offset The first dirty offset that the cleaner doesn't have to clean
   * @param maxWaitMs The maximum time in ms to wait for cleaner
   *
   * @return A boolean indicating whether the work has completed before timeout
   */
  def awaitCleaned(topic: String, part: Int, offset: Long, maxWaitMs: Long = 60000L): Boolean = {
    def isCleaned = cleanerManager.allCleanerCheckpoints.get(TopicAndPartition(topic, part)).fold(false)(_ >= offset)
    var remainingWaitMs = maxWaitMs
    while (!isCleaned && remainingWaitMs > 0) {
      val sleepTime = math.min(100, remainingWaitMs)
      Thread.sleep(sleepTime)
      remainingWaitMs -= sleepTime
    }
    isCleaned
  }

  /**
   * The cleaner threads do the actual log cleaning. Each thread processes does its cleaning repeatedly by
   * choosing the dirtiest log, cleaning it, and then swapping in the cleaned segments.
   */
  private class CleanerThread(threadId: Int)
    extends ShutdownableThread(name = "kafka-log-cleaner-thread-" + threadId, isInterruptible = false) {

    override val loggerName = classOf[LogCleaner].getName

    if(config.dedupeBufferSize / config.numThreads > Int.MaxValue)
      warn("Cannot use more than 2G of cleaner buffer space per cleaner thread, ignoring excess buffer space...")

    val cleaner = new Cleaner(id = threadId,
                              offsetMap = new SkimpyOffsetMap(memory = math.min(config.dedupeBufferSize / config.numThreads, Int.MaxValue).toInt,
                                                              hashAlgorithm = config.hashAlgorithm),
                              ioBufferSize = config.ioBufferSize / config.numThreads / 2,
                              maxIoBufferSize = config.maxMessageSize,
                              dupBufferLoadFactor = config.dedupeBufferLoadFactor,
                              throttler = throttler,
                              time = time,
                              checkDone = checkDone)

    @volatile var lastStats: CleanerStats = new CleanerStats()
    private val backOffWaitLatch = new CountDownLatch(1)

    private def checkDone(topicAndPartition: TopicAndPartition) {
      if (!isRunning.get())
        throw new ThreadShutdownException
      cleanerManager.checkCleaningAborted(topicAndPartition)
    }

    /**
     * The main loop for the cleaner thread
     */
    override def doWork() {
      cleanOrSleep()
    }

    override def shutdown() = {
    	 initiateShutdown()
    	 backOffWaitLatch.countDown()
    	 awaitShutdown()
     }

    /**
     * Clean a log if there is a dirty log available, otherwise sleep for a bit
     */
    private def cleanOrSleep() {
      val cleaned = cleanerManager.grabFilthiestCompactedLog(time) match {
        case None =>
          false
        case Some(cleanable) =>
          // there's a log, clean it
          var endOffset = cleanable.firstDirtyOffset
          try {
            endOffset = cleaner.clean(cleanable)
            recordStats(cleaner.id, cleanable.log.name, cleanable.firstDirtyOffset, endOffset, cleaner.stats)
          } catch {
            case pe: LogCleaningAbortedException => // task can be aborted, let it go.
          } finally {
            cleanerManager.doneCleaning(cleanable.topicPartition, cleanable.log.dir.getParentFile, endOffset)
          }
          true
      }
      val deletable: Iterable[(TopicAndPartition, Log)] = cleanerManager.deletableLogs()
      deletable.foreach{
        case (topicPartition, log) =>
          try {
            log.deleteOldSegments()
          } finally {
            cleanerManager.doneDeleting(topicPartition)
          }
      }
      if (!cleaned)
        backOffWaitLatch.await(config.backOffMs, TimeUnit.MILLISECONDS)
    }

    /**
     * Log out statistics on a single run of the cleaner.
     */
    def recordStats(id: Int, name: String, from: Long, to: Long, stats: CleanerStats) {
      this.lastStats = stats
      cleaner.statsUnderlying.swap
      def mb(bytes: Double) = bytes / (1024*1024)
      val message =
        "%n\tLog cleaner thread %d cleaned log %s (dirty section = [%d, %d])%n".format(id, name, from, to) +
        "\t%,.1f MB of log processed in %,.1f seconds (%,.1f MB/sec).%n".format(mb(stats.bytesRead),
                                                                                stats.elapsedSecs,
                                                                                mb(stats.bytesRead/stats.elapsedSecs)) +
        "\tIndexed %,.1f MB in %.1f seconds (%,.1f Mb/sec, %.1f%% of total time)%n".format(mb(stats.mapBytesRead),
                                                                                stats.elapsedIndexSecs,
                                                                                mb(stats.mapBytesRead)/stats.elapsedIndexSecs,
                                                                                100 * stats.elapsedIndexSecs/stats.elapsedSecs) +
        "\tBuffer utilization: %.1f%%%n".format(100 * stats.bufferUtilization) +
        "\tCleaned %,.1f MB in %.1f seconds (%,.1f Mb/sec, %.1f%% of total time)%n".format(mb(stats.bytesRead),
                                                                                stats.elapsedSecs - stats.elapsedIndexSecs,
                                                                                mb(stats.bytesRead)/(stats.elapsedSecs - stats.elapsedIndexSecs), 100 * (stats.elapsedSecs - stats.elapsedIndexSecs).toDouble/stats.elapsedSecs) +
        "\tStart size: %,.1f MB (%,d messages)%n".format(mb(stats.bytesRead), stats.messagesRead) +
        "\tEnd size: %,.1f MB (%,d messages)%n".format(mb(stats.bytesWritten), stats.messagesWritten) +
        "\t%.1f%% size reduction (%.1f%% fewer messages)%n".format(100.0 * (1.0 - stats.bytesWritten.toDouble/stats.bytesRead),
                                                                   100.0 * (1.0 - stats.messagesWritten.toDouble/stats.messagesRead))
      info(message)
      if (stats.invalidMessagesRead > 0) {
        warn("\tFound %d invalid messages during compaction.".format(stats.invalidMessagesRead))
      }
    }

  }
}

/**
 * This class holds the actual logic for cleaning a log
 * @param id An identifier used for logging
 * @param offsetMap The map used for deduplication
 * @param ioBufferSize The size of the buffers to use. Memory usage will be 2x this number as there is a read and write buffer.
 * @param maxIoBufferSize The maximum size of a message that can appear in the log
 * @param dupBufferLoadFactor The maximum percent full for the deduplication buffer
 * @param throttler The throttler instance to use for limiting I/O rate.
 * @param time The time instance
 * @param checkDone Check if the cleaning for a partition is finished or aborted.
 */
private[log] class Cleaner(val id: Int,
                           val offsetMap: OffsetMap,
                           ioBufferSize: Int,
                           maxIoBufferSize: Int,
                           dupBufferLoadFactor: Double,
                           throttler: Throttler,
                           time: Time,
                           checkDone: (TopicAndPartition) => Unit) extends Logging {

  override val loggerName = classOf[LogCleaner].getName

  this.logIdent = "Cleaner " + id + ": "

  /* cleaning stats - one instance for the current (or next) cleaning cycle and one for the last completed cycle */
  val statsUnderlying = (new CleanerStats(time), new CleanerStats(time))
  def stats = statsUnderlying._1

  /* buffer used for read i/o */
  private var readBuffer = ByteBuffer.allocate(ioBufferSize)

  /* buffer used for write i/o */
  private var writeBuffer = ByteBuffer.allocate(ioBufferSize)

  require(offsetMap.slots * dupBufferLoadFactor > 1, "offset map is too small to fit in even a single message, so log cleaning will never make progress. You can increase log.cleaner.dedupe.buffer.size or decrease log.cleaner.threads")

  /**
   * Clean the given log
   *
   * @param cleanable The log to be cleaned
   *
   * @return The first offset not cleaned
   */
  private[log] def clean(cleanable: LogToClean): Long = {
    stats.clear()
    info("Beginning cleaning of log %s.".format(cleanable.log.name))
    val log = cleanable.log

    // build the offset map
    info("Building offset map for %s...".format(cleanable.log.name))
    val upperBoundOffset = cleanable.firstUncleanableOffset
    buildOffsetMap(log, cleanable.firstDirtyOffset, upperBoundOffset, offsetMap)
    val endOffset = offsetMap.latestOffset + 1
    stats.indexDone()

    // figure out the timestamp below which it is safe to remove delete tombstones
    // this position is defined to be a configurable time beneath the last modified time of the last clean segment
    val deleteHorizonMs =
      log.logSegments(0, cleanable.firstDirtyOffset).lastOption match {
        case None => 0L
        case Some(seg) => seg.largestTimestamp - log.config.deleteRetentionMs
    }

    // determine the timestamp up to which the log will be cleaned
    // this is the lower of the last active segment and the compaction lag
    val cleanableHorizionMs = log.logSegments(0, cleanable.firstUncleanableOffset).lastOption.map(_.largestTimestamp).getOrElse(0L)

    // group the segments and clean the groups
    info("Cleaning log %s (cleaning prior to %s, discarding tombstones prior to %s)...".format(log.name, new Date(cleanableHorizionMs), new Date(deleteHorizonMs)))
    for (group <- groupSegmentsBySize(log.logSegments(0, endOffset), log.config.segmentSize, log.config.maxIndexSize))
      cleanSegments(log, group, offsetMap, deleteHorizonMs)

    // record buffer utilization
    stats.bufferUtilization = offsetMap.utilization

    stats.allDone()

    endOffset
  }

  /**
   * Clean a group of segments into a single replacement segment
   *
   * @param log The log being cleaned
   * @param segments The group of segments being cleaned
   * @param map The offset map to use for cleaning segments
   * @param deleteHorizonMs The time to retain delete tombstones
   */
  private[log] def cleanSegments(log: Log,
                                 segments: Seq[LogSegment],
                                 map: OffsetMap,
                                 deleteHorizonMs: Long) {
    // create a new segment with the suffix .cleaned appended to both the log and index name
    val logFile = new File(segments.head.log.file.getPath + Log.CleanedFileSuffix)
    logFile.delete()
    val indexFile = new File(segments.head.index.file.getPath + Log.CleanedFileSuffix)
    val timeIndexFile = new File(segments.head.timeIndex.file.getPath + Log.CleanedFileSuffix)
    indexFile.delete()
    timeIndexFile.delete()
    val messages = new FileMessageSet(logFile, fileAlreadyExists = false, initFileSize = log.initFileSize(), preallocate = log.config.preallocate)
    val index = new OffsetIndex(indexFile, segments.head.baseOffset, segments.head.index.maxIndexSize)
    val timeIndex = new TimeIndex(timeIndexFile, segments.head.baseOffset, segments.head.timeIndex.maxIndexSize)
    val cleaned = new LogSegment(messages, index, timeIndex, segments.head.baseOffset, segments.head.indexIntervalBytes, log.config.randomSegmentJitter, time)

    try {
      // clean segments into the new destination segment
      for (old <- segments) {
        val retainDeletes = old.largestTimestamp > deleteHorizonMs
        info("Cleaning segment %s in log %s (largest timestamp %s) into %s, %s deletes."
            .format(old.baseOffset, log.name, new Date(old.largestTimestamp), cleaned.baseOffset, if(retainDeletes) "retaining" else "discarding"))
        cleanInto(log.topicAndPartition, old, cleaned, map, retainDeletes, log.config.maxMessageSize)
      }

      // trim excess index
      index.trimToValidSize()

      // Append the last index entry
      cleaned.onBecomeInactiveSegment()

      // trim time index
      timeIndex.trimToValidSize()

      // flush new segment to disk before swap
      cleaned.flush()

      // update the modification date to retain the last modified date of the original files
      val modified = segments.last.lastModified
      cleaned.lastModified = modified

      // swap in new segment
      info("Swapping in cleaned segment %d for segment(s) %s in log %s.".format(cleaned.baseOffset, segments.map(_.baseOffset).mkString(","), log.name))
      log.replaceSegments(cleaned, segments)
    } catch {
      case e: LogCleaningAbortedException =>
        cleaned.delete()
        throw e
    }
  }

  /**
   * Clean the given source log segment into the destination segment using the key=>offset mapping
   * provided
   *
   * @param topicAndPartition The topic and partition of the log segment to clean
   * @param source The dirty log segment
   * @param dest The cleaned log segment
   * @param map The key=>offset mapping
   * @param retainDeletes Should delete tombstones be retained while cleaning this segment
   * @param maxLogMessageSize The maximum message size of the corresponding topic
   */
  private[log] def cleanInto(topicAndPartition: TopicAndPartition,
                             source: LogSegment,
                             dest: LogSegment,
                             map: OffsetMap,
                             retainDeletes: Boolean,
                             maxLogMessageSize: Int) {
    var position = 0
    while (position < source.log.sizeInBytes) {
      checkDone(topicAndPartition)
      // read a chunk of messages and copy any that are to be retained to the write buffer to be written out
      readBuffer.clear()
      writeBuffer.clear()
      var maxTimestamp = Message.NoTimestamp
      var offsetOfMaxTimestamp = -1L
      val messages = new ByteBufferMessageSet(source.log.readInto(readBuffer, position))
      throttler.maybeThrottle(messages.sizeInBytes)
      // check each message to see if it is to be retained
      var messagesRead = 0
      for (shallowMessageAndOffset <- messages.shallowIterator) {
        val shallowMessage = shallowMessageAndOffset.message
        val shallowOffset = shallowMessageAndOffset.offset
        val size = MessageSet.entrySize(shallowMessageAndOffset.message)

        stats.readMessage(size)
        if (shallowMessage.compressionCodec == NoCompressionCodec) {
          if (shouldRetainMessage(source, map, retainDeletes, shallowMessageAndOffset)) {
            ByteBufferMessageSet.writeMessage(writeBuffer, shallowMessage, shallowOffset)
            stats.recopyMessage(size)
            if (shallowMessage.timestamp > maxTimestamp) {
              maxTimestamp = shallowMessage.timestamp
              offsetOfMaxTimestamp = shallowOffset
            }
          }
          messagesRead += 1
        } else {
          // We use the absolute offset to decide whether to retain the message or not (this is handled by the
          // deep iterator). Because of KAFKA-4298, we have to allow for the possibility that a previous version
          // corrupted the log by writing a compressed message set with a wrapper magic value not matching the magic
          // of the inner messages. This will be fixed as we recopy the messages to the destination segment.

          var writeOriginalMessageSet = true
          val retainedMessages = new mutable.ArrayBuffer[MessageAndOffset]
          val shallowMagic = shallowMessage.magic

          for (deepMessageAndOffset <- ByteBufferMessageSet.deepIterator(shallowMessageAndOffset)) {
            messagesRead += 1
            if (shouldRetainMessage(source, map, retainDeletes, deepMessageAndOffset)) {
              // Check for log corruption due to KAFKA-4298. If we find it, make sure that we overwrite
              // the corrupted entry with correct data.
              if (shallowMagic != deepMessageAndOffset.message.magic)
                writeOriginalMessageSet = false

              retainedMessages += deepMessageAndOffset
              // We need the max timestamp and last offset for time index
              if (deepMessageAndOffset.message.timestamp > maxTimestamp)
                maxTimestamp = deepMessageAndOffset.message.timestamp
            } else {
              writeOriginalMessageSet = false
            }
          }
          offsetOfMaxTimestamp = if (retainedMessages.nonEmpty) retainedMessages.last.offset else -1L
          // There are no messages compacted out and no message format conversion, write the original message set back
          if (writeOriginalMessageSet)
            ByteBufferMessageSet.writeMessage(writeBuffer, shallowMessage, shallowOffset)
          else
            compressMessages(writeBuffer, shallowMessage.compressionCodec, retainedMessages)
        }
      }

      position += messages.validBytes
      // if any messages are to be retained, write them out
      if (writeBuffer.position > 0) {
        writeBuffer.flip()
        val retained = new ByteBufferMessageSet(writeBuffer)
        dest.append(firstOffset = retained.head.offset, largestTimestamp = maxTimestamp,
          offsetOfLargestTimestamp = offsetOfMaxTimestamp, messages = retained)
        throttler.maybeThrottle(writeBuffer.limit)
      }

      // if we read bytes but didn't get even one complete message, our I/O buffer is too small, grow it and try again
      if (readBuffer.limit > 0 && messagesRead == 0)
        growBuffers(maxLogMessageSize)
    }
    restoreBuffers()
  }

  private def compressMessages(buffer: ByteBuffer,
                               compressionCodec: CompressionCodec,
                               messageAndOffsets: Seq[MessageAndOffset]) {
    require(compressionCodec != NoCompressionCodec, s"compressionCodec must not be $NoCompressionCodec")
    if (messageAndOffsets.nonEmpty) {
      val messages = messageAndOffsets.map(_.message)
      val magicAndTimestamp = MessageSet.magicAndLargestTimestamp(messages)

      // ensure that we use the magic from the first message in the set when writing the wrapper
      // message in order to fix message sets corrupted by KAFKA-4298
      val magic = magicAndTimestamp.magic

      val firstMessageOffset = messageAndOffsets.head
      val firstAbsoluteOffset = firstMessageOffset.offset
      var offset = -1L
      val timestampType = firstMessageOffset.message.timestampType
      val messageWriter = new MessageWriter(math.min(math.max(MessageSet.messageSetSize(messages) / 2, 1024), 1 << 16))
      messageWriter.write(codec = compressionCodec, timestamp = magicAndTimestamp.timestamp, timestampType = timestampType, magicValue = magic) { outputStream =>
        val output = new DataOutputStream(CompressionFactory(compressionCodec, magic, outputStream))
        try {
          for (messageAndOffset <- messageAndOffsets) {
            offset = messageAndOffset.offset
            val innerOffset = if (magic > Message.MagicValue_V0)
              // The offset of the messages are absolute offset, compute the inner offset.
              messageAndOffset.offset - firstAbsoluteOffset
            else
              offset

            val message = messageAndOffset.message
            output.writeLong(innerOffset)
            output.writeInt(message.size)
            output.write(message.buffer.array, message.buffer.arrayOffset, message.buffer.limit)
          }
        } finally {
          output.close()
        }
      }
      ByteBufferMessageSet.writeMessage(buffer, messageWriter, offset)
      stats.recopyMessage(messageWriter.size + MessageSet.LogOverhead)
    }
  }

  private def shouldRetainMessage(source: kafka.log.LogSegment,
                                  map: kafka.log.OffsetMap,
                                  retainDeletes: Boolean,
                                  entry: kafka.message.MessageAndOffset): Boolean = {
    val pastLatestOffset = entry.offset > map.latestOffset
    if (pastLatestOffset)
      return true

    val key = entry.message.key
    if (key != null) {
      val foundOffset = map.get(key)
      /* two cases in which we can get rid of a message:
       *   1) if there exists a message with the same key but higher offset
       *   2) if the message is a delete "tombstone" marker and enough time has passed
       */
      val redundant = foundOffset >= 0 && entry.offset < foundOffset
      val obsoleteDelete = !retainDeletes && entry.message.isNull
      !redundant && !obsoleteDelete
    } else {
      stats.invalidMessage()
      false
    }
  }

  /**
   * Double the I/O buffer capacity
   */
  def growBuffers(maxLogMessageSize: Int) {
    val maxBufferSize = math.max(maxLogMessageSize, maxIoBufferSize)
    if(readBuffer.capacity >= maxBufferSize || writeBuffer.capacity >= maxBufferSize)
      throw new IllegalStateException("This log contains a message larger than maximum allowable size of %s.".format(maxBufferSize))
    val newSize = math.min(this.readBuffer.capacity * 2, maxBufferSize)
    info("Growing cleaner I/O buffers from " + readBuffer.capacity + "bytes to " + newSize + " bytes.")
    this.readBuffer = ByteBuffer.allocate(newSize)
    this.writeBuffer = ByteBuffer.allocate(newSize)
  }

  /**
   * Restore the I/O buffer capacity to its original size
   */
  def restoreBuffers() {
    if(this.readBuffer.capacity > this.ioBufferSize)
      this.readBuffer = ByteBuffer.allocate(this.ioBufferSize)
    if(this.writeBuffer.capacity > this.ioBufferSize)
      this.writeBuffer = ByteBuffer.allocate(this.ioBufferSize)
  }

  /**
   * Group the segments in a log into groups totaling less than a given size. the size is enforced separately for the log data and the index data.
   * We collect a group of such segments together into a single
   * destination segment. This prevents segment sizes from shrinking too much.
   *
   * @param segments The log segments to group
   * @param maxSize the maximum size in bytes for the total of all log data in a group
   * @param maxIndexSize the maximum size in bytes for the total of all index data in a group
   *
   * @return A list of grouped segments
   */
  private[log] def groupSegmentsBySize(segments: Iterable[LogSegment], maxSize: Int, maxIndexSize: Int): List[Seq[LogSegment]] = {
    var grouped = List[List[LogSegment]]()
    var segs = segments.toList
    while(segs.nonEmpty) {
      var group = List(segs.head)
      var logSize = segs.head.size
      var indexSize = segs.head.index.sizeInBytes
      var timeIndexSize = segs.head.timeIndex.sizeInBytes
      segs = segs.tail
      while(segs.nonEmpty &&
            logSize + segs.head.size <= maxSize &&
            indexSize + segs.head.index.sizeInBytes <= maxIndexSize &&
            timeIndexSize + segs.head.timeIndex.sizeInBytes <= maxIndexSize &&
            segs.head.index.lastOffset - group.last.index.baseOffset <= Int.MaxValue) {
        group = segs.head :: group
        logSize += segs.head.size
        indexSize += segs.head.index.sizeInBytes
        timeIndexSize += segs.head.timeIndex.sizeInBytes
        segs = segs.tail
      }
      grouped ::= group.reverse
    }
    grouped.reverse
  }

  /**
   * Build a map of key_hash => offset for the keys in the cleanable dirty portion of the log to use in cleaning.
   * @param log The log to use
   * @param start The offset at which dirty messages begin
   * @param end The ending offset for the map that is being built
   * @param map The map in which to store the mappings
   */
  private[log] def buildOffsetMap(log: Log, start: Long, end: Long, map: OffsetMap) {
    map.clear()
    val dirty = log.logSegments(start, end).toBuffer
    info("Building offset map for log %s for %d segments in offset range [%d, %d).".format(log.name, dirty.size, start, end))

    // Add all the cleanable dirty segments. We must take at least map.slots * load_factor,
    // but we may be able to fit more (if there is lots of duplication in the dirty section of the log)
    var full = false
    for (segment <- dirty if !full) {
      checkDone(log.topicAndPartition)

      full = buildOffsetMapForSegment(log.topicAndPartition, segment, map, start, log.config.maxMessageSize)
      if (full)
        debug("Offset map is full, %d segments fully mapped, segment with base offset %d is partially mapped".format(dirty.indexOf(segment), segment.baseOffset))
    }
    info("Offset map for log %s complete.".format(log.name))
  }

  /**
   * Add the messages in the given segment to the offset map
   *
   * @param segment The segment to index
   * @param map The map in which to store the key=>offset mapping
   *
   * @return If the map was filled whilst loading from this segment
   */
  private def buildOffsetMapForSegment(topicAndPartition: TopicAndPartition, segment: LogSegment, map: OffsetMap, start: Long, maxLogMessageSize: Int): Boolean = {
    var position = segment.index.lookup(start).position
    val maxDesiredMapSize = (map.slots * this.dupBufferLoadFactor).toInt
    while (position < segment.log.sizeInBytes) {
      checkDone(topicAndPartition)
      readBuffer.clear()
      val messages = new ByteBufferMessageSet(segment.log.readInto(readBuffer, position))
      throttler.maybeThrottle(messages.sizeInBytes)
      val startPosition = position
      for (entry <- messages) {
        val message = entry.message
        if (message.hasKey && entry.offset >= start) {
          if (map.size < maxDesiredMapSize)
            map.put(message.key, entry.offset)
          else
            return true
        }
        stats.indexMessagesRead(1)
      }
      position += messages.validBytes
      stats.indexBytesRead(messages.validBytes)

      // if we didn't read even one complete message, our read buffer may be too small
      if(position == startPosition)
        growBuffers(maxLogMessageSize)
    }
    restoreBuffers()
    return false
  }
}

/**
 * A simple struct for collecting stats about log cleaning
 */
private case class CleanerStats(time: Time = SystemTime) {
  var startTime, mapCompleteTime, endTime, bytesRead, bytesWritten, mapBytesRead, mapMessagesRead, messagesRead,
      messagesWritten, invalidMessagesRead = 0L
  var bufferUtilization = 0.0d
  clear()

  def readMessage(size: Int) {
    messagesRead += 1
    bytesRead += size
  }

  def invalidMessage() {
    invalidMessagesRead += 1
  }

  def recopyMessage(size: Int) {
    messagesWritten += 1
    bytesWritten += size
  }

  def indexMessagesRead(size: Int) {
    mapMessagesRead += size
  }

  def indexBytesRead(size: Int) {
    mapBytesRead += size
  }

  def indexDone() {
    mapCompleteTime = time.milliseconds
  }

  def allDone() {
    endTime = time.milliseconds
  }

  def elapsedSecs = (endTime - startTime)/1000.0

  def elapsedIndexSecs = (mapCompleteTime - startTime)/1000.0

  def clear() {
    startTime = time.milliseconds
    mapCompleteTime = -1L
    endTime = -1L
    bytesRead = 0L
    bytesWritten = 0L
    mapBytesRead = 0L
    mapMessagesRead = 0L
    messagesRead = 0L
    invalidMessagesRead = 0L
    messagesWritten = 0L
    bufferUtilization = 0.0d
  }
}

/**
 * Helper class for a log, its topic/partition, the first cleanable position, and the first uncleanable dirty position
 */
private case class LogToClean(topicPartition: TopicAndPartition, log: Log, firstDirtyOffset: Long, uncleanableOffset: Long) extends Ordered[LogToClean] {
  val cleanBytes = log.logSegments(-1, firstDirtyOffset).map(_.size).sum
  private[this] val firstUncleanableSegment = log.logSegments(uncleanableOffset, log.activeSegment.baseOffset).headOption.getOrElse(log.activeSegment)
  val firstUncleanableOffset = firstUncleanableSegment.baseOffset
  val cleanableBytes = log.logSegments(firstDirtyOffset, math.max(firstDirtyOffset, firstUncleanableOffset)).map(_.size).sum
  val totalBytes = cleanBytes + cleanableBytes
  val cleanableRatio = cleanableBytes / totalBytes.toDouble
  override def compare(that: LogToClean): Int = math.signum(this.cleanableRatio - that.cleanableRatio).toInt
}


Many people think that BLOOD orange means a deeper, darker, richer orange flavor... they are MISTAKEN!!!! Our BLOOD ORANGE premium e-juice is, by every definition... it's own flavor!!! With a lighter, completeley UNIQUE taste (some say bitter), Blood Orange falls in more of the grapefruit family than it does oranges... but don't worry, we've added the perfect touch of sweetness that won't leave your mouth puckered for too long!
I can't describe this delicious flavor to the degree it needs. Tart but sweet. Always satisfying. Became my all day vape the first time I had it.


text:
package org.ihtsdo.json.model.versioned;

/**
 *
 * @author Alejandro Rodriguez
 */

public class Relationship extends Component {

    private ConceptDescriptor type;
    private ConceptDescriptor target;
    private Long sourceId;
    private Integer groupId;
    private ConceptDescriptor charType;
    private String modifier;

    public Relationship() {
        super();
    }

	public ConceptDescriptor getType() {
		return type;
	}

	public void setType(ConceptDescriptor type) {
		this.type = type;
	}

	public ConceptDescriptor getTarget() {
		return target;
	}

	public void setTarget(ConceptDescriptor target) {
		this.target = target;
	}

	public Long getSourceId() {
		return sourceId;
	}

	public void setSourceId(Long sourceId) {
		this.sourceId = sourceId;
	}

	public Integer getGroupId() {
		return groupId;
	}

	public void setGroupId(Integer groupId) {
		this.groupId = groupId;
	}

	public ConceptDescriptor getCharType() {
		return charType;
	}

	public void setCharType(ConceptDescriptor charType) {
		this.charType = charType;
	}

	public String getModifier() {
		return modifier;
	}

	public void setModifier(String modifier) {
		this.modifier = modifier;
	}

}


text:
PHWA President Kevin Allen named Elmer Ferguson winner
Posted on June 5, 2014 | by mihai
Huge congrats to PHWA president Kevin Allen, honored today by the Hockey Hall of Fame as this year's Elmer Ferguson award winner.
Full details in the press release below from the Hockey Hall of Fame:
TORONTO (June 5, 2014) – Eric Duhatschek, Vice-President, Professional Hockey Writers' Association, and Chuck Kaiton, President of the NHL Broadcasters' Association, announced today that KEVIN ALLEN will receive the Elmer Ferguson Memorial Award for excellence in hockey journalism and PAT FOLEY will receive the Foster Hewitt Memorial Award for outstanding contributions as a hockey broadcaster.
Kevin Allen has been USA Today's hockey expert since 1986, and is the only writer to make Hockey News' Top 100 list of most influential people in the sport each year of the list existence. In 2013, Kevin received the Lester Patrick Trophy for outstanding service to hockey in the United States, only the fifth media member so honoured since the award debuted in 1966. He has also written 17 hockey books.
Over the past three decades Allen has covered 600 NHL playoff games, eight Olympics, and 27 Stanley Cup finals, plus Canada Cups, World Cups and World Championships.
"Kevin has managed a neat trick over the years, writing definitive and authoritative hockey commentary in a publication that requires its writers to be tight and bright," said Duhatschek. "Kevin is the most well-connected of the U.S. based writers and was an 'insider' long before the term became ubiquitous."
Television play-by-play announcer Pat Foley – the voice of the Chicago Blackhawks – is now in his 31st season with the team. The Illinois native began his broadcasting career as a student at Michigan State University, calling baseball and hockey games for the school. Since his professional debut with the International Hockey League's Grand Rapids Owls in 1977, Foley has won three Emmy awards and was inducted into the Chicagoland Sports Hall of Fame in 2002.
"Pat Foley is extremely worthy of this distinction," said Kaiton. "This legend's voice and style have been a unique part of Blackhawk hockey for almost four decades."
Foley and Allen will receive their awards at the Hockey Hall of Fame NHL Media Awards Luncheon presentation in Toronto on Monday, November 17th, and their award plaques will be displayed in the Esso Great Hall at the Hockey Hall of Fame alongside the 90 past award recipients.
Recipients of these awards, as selected by their respective associations, are recognized by the Hockey Hall of Fame as "Media Honourees" ─ a separate distinction from individuals inducted as "Honoured Members" by the Hockey Hall of Fame Selection Committee.
Named in honour of the late Montreal newspaper reporter, the Elmer Ferguson Memorial Award was first presented in 1984 by the Professional Hockey Writers' Association in recognition of distinguished members of the hockey writing profession whose words have brought honour to journalism and to the game of hockey.
Named in honour of the late "Voice of Hockey" in Canada, the Foster Hewitt Memorial Award was first presented in 1984 by the NHL Broadcasters' Association in recognition of members of the radio and television industry who have made outstanding contributions to their profession and to the game of hockey.
Posted in News | Tagged Awards
Masterton Nominations
PHWA Award Voting Totals