text:
Proposed Redesign For Load, Store, and Slicer in Pig
The current design of LoadFunc, StoreFunc, and the Slicer interfaces in Pig are not adequate. This proposed redesign has the following goals:
The Slicer interface is redundant. Remove it and allow users to directly use Hadoop InputFormats in Pig.
It is not currently easy to use a separate OutputFormat for a StoreFunc. This should be made easy to allow users to store data into locations other than HDFS.
Currently users that wish to operate on Pig and Map-Reduce are required to write Hadoop InputFormat and OutputFormat as well as a Pig load and storage functions. While Pig load and store functions will always be necessary to take the most advantage of Hadoop, it would be good for users to be able to use Hadoop InputFormat and OutputFormat classes directly to minimize the data interchange cost.
New storage formats such as Zebra are being implemented for Hadoop that include metadata information such as schema, etc. The LoadFunc interface needs to allow Pig to obtain this metadata. There is a describeSchema call in the current interface. More functions may be necessary.
- These new storage formats also plan to support pushing of, at least, projection and selection into the storage layer. Pig needs to be able to query loaders to determine what if any pushdown capabilities they support and then make use of those capabilities.
- There already exists one metadata system in Hadoop (Hive's metastore) and there is a proposal to add another (Owl). Pig needs to be able to query these metadata systems for information about data to be read. It also needs to be able to record information to these metadata systems when writing data. The load and store functions are a reasonable place to do these operations since that is the point at which Pig is reading and writing data. This will also allow Pig to read and write data from and to multiple metadata stores in single Pig Latin scripts if that is desired.
A requirement for the implementation that does not fit into the goals above is that while the existing Pig implementation is tightly tied to Hadoop (and is becoming more tightly tied all the time), we do not want to tie Pig Latin tightly to Hadoop. Therefore while we plan to allow users to easily interact with Hadoop InputFormats and OutputFormats, these should not be exposed as such to Pig Latin. Pig Latin must still view these as load and store functions; it will only be the underlying implementation that will realize that they are Hadoop classes and handle them appropriately.
With these proposed changes, load and store functions in Pig are becoming very weighty objects. The current LoadFunc interface already provides mechanisms for reading the data, getting some schema information, casting data, and some place holders for pushing down projections into the loader. This proposal will add more file level metadata, selection push down, plus interaction with InputFormats. It will also add OutputFormats to store functions. If we create two monster interfaces that attempt to provide everything, the burden of creating a new load or store function in Pig will become overwhelming. Instead, this proposal envisions splitting the interface into a number of interfaces, each with a clear responsibility. Load and store functions will then only be required to implement the interfaces for functionality they offer.
For load functions:
LoadFunc will be pared down to just contain functions directly associated with reading data, such as getNext. LoadFunc will now be an abstract class with default implementations for some of the methods.
A new LoadCaster interface will be added. This interface will contain all of the bytesToX methods currently in LoadFunc. LoadFunc will add a getCaster routine, that will return an object that can provide casts. The existing UTF8!StorageConverter class will change to implement this interface. Load functions will then be free to use this class as their caster, or provide their own. For existing load functions that provide all of the bytesToX methods, they can implement the LoadCaster interface and return themselves from the getCaster routine. If a loader does not provide a LoadCaster, casts from byte array to other Pig types will not be supported for data loaded via that loader.
A new LoadMetadata interface will be added. Calls that find metadata about the data being loaded, such as determineSchema, will be placed in this interface. If a loader does not implement this interface, then Pig will assume that no metadata is obtainable for this data.
A new LoadPushDown interface will be added. Calls that determine what can be pushed down and pushing that functionality down into the loader will be placed in this interface. If a loader does not implement this interface, then Pig will assume that the loader is not capable of pushing down any functionality.
For store functions:
A new method getOutputFormat will be added to StoreFunc to allow a storage function to return its output format.
A new interface StoreMetadata will be added to provide a way for storage functions to record metadata. If a given storage function does not implement this interface Pig will assume that it is unable to record metadata.
LoadFunc (For brevity, getAbsolutePath() method's implementation is not shown below)
/** * LoadFunc provides functions directly associated with reading * records from data set. */ public abstract class LoadFunc { /** * This method is called by the Pig runtime in the front end to convert the * input location to an absolute path if the location is relative. The * loadFunc implementation is free to choose how it converts a relative * location to an absolute location since this may depend on what the location * string represent (hdfs path or some other data source) * * @param location location as provided in the "load" statement of the script * @param curDir the current working direction based on any "cd" statements * in the script before the "load" statement. If there are no "cd" statements * in the script, this would be the home directory - *
/user/<username>
 * @return the absolute location based on the arguments passed * @throws IOException if the conversion is not possible */ public String relativeToAbsolutePath(String location, Path curDir) throws IOException { return getAbsolutePath(location, curDir); } /** * Communicate to the loader the location of the object(s) being loaded. * The location string passed to the LoadFunc here is the return value of * {@link LoadFunc#relativeToAbsolutePath(String, Path)}. Implementations * should use this method to communicate the location (and any other information) * to its underlying InputFormat through the Job object. * * This method will be called in the backend multiple times. Implementations * should bear in mind that this method is called multiple times and should * ensure there are no inconsistent side effects due to the multiple calls. * * @param location Location as returned by * {@link LoadFunc#relativeToAbsolutePath(String, Path)} * @param job the {@link Job} object * store or retrieve earlier stored information from the {@link UDFContext} * @throws IOException if the location is not valid. */ public abstract void setLocation(String location, Job job) throws IOException; /** * This will be called during planning on the front end. This is the * instance of InputFormat (rather than the class name) because the * load function may need to instantiate the InputFormat in order * to control how it is constructed. * @return the InputFormat associated with this loader. * @throws IOException if there is an exception during InputFormat * construction */ @SuppressWarnings("unchecked") public abstract InputFormat getInputFormat() throws IOException; /** * This will be called on the front end during planning and not on the back * end during execution. * @return the {@link LoadCaster} associated with this loader. Returning null * indicates that casts from byte array are not supported for this loader. * construction * @throws IOException if there is an exception during LoadCaster */ public LoadCaster getLoadCaster() throws IOException { return new Utf8StorageConverter(); } /** * Initializes LoadFunc for reading data. This will be called during execution * before any calls to getNext. The RecordReader needs to be passed here because * it has been instantiated for a particular InputSplit. * @param reader {@link RecordReader} to be used by this instance of the LoadFunc * @param split The input {@link PigSplit} to process * @throws IOException if there is an exception during initialization */ @SuppressWarnings("unchecked") public abstract void prepareToRead(RecordReader reader, PigSplit split) throws IOException; /** * Retrieves the next tuple to be processed. Implementations should NOT reuse * tuple objects (or inner member objects) they return across calls and * should return a different tuple object in each call. * @return the next tuple to be processed or null if there are no more tuples * to be processed. * @throws IOException if there is an exception while retrieving the next * tuple */ public abstract Tuple getNext() throws IOException; /** * This method will be called by Pig both in the front end and back end to * pass a unique signature to the {@link LoadFunc}. The signature can be used * to store into the {@link UDFContext} any information which the * {@link LoadFunc} needs to store between various method invocations in the * front end and back end. A use case is to store {@link RequiredFieldList} * passed to it in {@link LoadPushDown#pushProjection(RequiredFieldList)} for * use in the back end before returning tuples in {@link LoadFunc#getNext()}. * This method will be call before other methods in {@link LoadFunc} * @param signature a unique signature to identify this LoadFunc */ public void setUDFContextSignature(String signature) { // default implementation is a no-op } }
The LoadCaster interface will include bytesToInt, bytesToLong, etc. functions currently in LoadFunc. UTF8!StorageConverter will implement this interface. The only change will be in bytesToTuple() and bytesToBag() - these methods will take an additional ResourceFieldSchema argument describing the schema of the tuple and bag respectively that the bytes need to be cast to.
/** * This interface defines how to retrieve metadata related to data to be loaded. * If a given loader does not implement this interface, it will be assumed that it * is unable to provide metadata about the associated data. */ public interface LoadMetadata { /** * Get a schema for the data to be loaded. * @param location Location as returned by * {@link LoadFunc#relativeToAbsolutePath(String, org.apache.hadoop.fs.Path)} * @param job The {@link Job} object - this should be used only to obtain * cluster properties through {@link Job#getConfiguration()} and not to set/query * any runtime job information. * @return schema for the data to be loaded. This schema should represent * all tuples of the returned data. If the schema is unknown or it is * not possible to return a schema that represents all returned data, * then null should be returned. * @throws IOException if an exception occurs while determining the schema */ ResourceSchema getSchema(String location, Job job) throws IOException; /** * Get statistics about the data to be loaded. If no statistics are * available, then null should be returned. * @param location Location as returned by * {@link LoadFunc#relativeToAbsolutePath(String, org.apache.hadoop.fs.Path)} * @param job The {@link Job} object - this should be used only to obtain * cluster properties through {@link Job#getConfiguration()} and not to set/query * any runtime job information. * @return statistics about the data to be loaded. If no statistics are * available, then null should be returned. * @throws IOException if an exception occurs while retrieving statistics */ ResourceStatistics getStatistics(String location, Job job) throws IOException; /** * Find what columns are partition keys for this input. * @param location Location as returned by * {@link LoadFunc#relativeToAbsolutePath(String, org.apache.hadoop.fs.Path)} * @param job The {@link Job} object - this should be used only to obtain * cluster properties through {@link Job#getConfiguration()} and not to set/query * any runtime job information. * @return array of field names of the partition keys. Implementations * should return null to indicate that there are no partition keys * @throws IOException if an exception occurs while retrieving partition keys */ String[] getPartitionKeys(String location, Job job) throws IOException; /** * Set the filter for partitioning. It is assumed that this filter * will only contain references to fields given as partition keys in * getPartitionKeys. So if the implementation returns null in * {@link #getPartitionKeys(String, Job)}, then this method is not * called by pig runtime. This method is also not called by the pig runtime * if there are no partition filter conditions. * @param partitionFilter that describes filter for partitioning * @throws IOException if the filter is not compatible with the storage * mechanism or contains non-partition fields. */ void setPartitionFilter(Expression partitionFilter) throws IOException; }
ResourceSchema will be a top level object (org.apache.pig.ResourceSchema) used to communicate information about data to be loaded or that is being stored. It is not the same as the existing org.apache.pig.impl.logicalLayer.schema.Schema.
public class ResourceSchema { int version; public class ResourceFieldSchema { public String name; public DataType type; public String description; public ResourceFieldSchema schema; // nested tuples and bags will have their own schema } public ResourceFieldSchema[] fields; enum Order { ASCENDING, DESCENDING } public int[] sortKeys; // each entry is an offset into the fields array. public Order[] sortKeyOrders; }
IMPORTANT NOTE:: In the ResourceFieldSchema for a bag field, the only field allowed in the subschema is a tuple field. The tuple itself can have a schema with more than 1 fields.
public class ResourceStatistics { public class ResourceFieldStatistics { int version; enum Distribution {UNIFORM, NORMAL, POWER}; public long numDistinctValues; // number of distinct values represented in this field public Distribution distribution; // how values in this field are distributed // We need some way to represent a histogram of values in the field, // as those will be useful. However, we can't count on being // able to hold such histograms in memory. Have to figure out // how they can be kept on disk and represented here. // Probably more in here } public long mBytes; // "disk" size in megabytes (file size or equivalent) public long numRecords; // number of records public ResourceFieldStatistics[] fields; // Probably more in here }
At this point, ResourceStatistics is poorly understood. In initial versions we may choose not to implement it. In additions to questions on what should be in the statistics, there are questions on how statistics should be communicated in relation to partitions. For example, when loading from a table that is stored in owl or hive, one or more partitions may be being loaded. Assuming statistics are kept on the partition level, how are these statistics then communicated to Pig? Is it the loader's job to combine the statistics for all of the partitions being read? Or does it return an array of ResourceStatistics? But if so, what does Pig do with it since it does not know which tuples belong to which partitions (and doesn't want to know). Even worse on store, any statistics Pig has to report is across all data being stored. But the storage function underneath may choose to partition the data. How does it then separate those statistics for the different partitions? In these cases should store functions be in charge of calculating statistics? Perhaps some statistics that can be easily distributed across partitions (such as distribution types) should be calculated and sent down by Pig and some left to the store functions. Perhaps statistics on store should instead be driven by call backs that Pig could define and implement and store functions should call after data has been partitioned if they want to.
/** * This interface defines how to communicate to Pig what functionality can * be pushed into the loader. If a given loader does not implement this interface * it will be assumed that it is unable to accept any functionality for push down. */ public interface LoadPushDown { /** * Set of possible operations that Pig can push down to a loader. */ enum OperatorSet {PROJECTION}; /** * Determine the operators that can be pushed to the loader. * Note that by indicating a loader can accept a certain operator * (such as selection) the loader is not promising that it can handle * all selections. When it is passed the actual operators to * push down it will still have a chance to reject them. * @return list of all features that the loader can support */ List<OperatorSet> getFeatures(); /** * Indicate to the loader fields that will be needed. This can be useful for * loaders that access data that is stored in a columnar format where indicating * columns to be accessed a head of time will save scans. This method will * not be invoked by the Pig runtime if all fields are required. So implementations * should assume that if this method is not invoked, then all fields from * the input are required. If the loader function cannot make use of this * information, it is free to ignore it by returning an appropriate Response * @param requiredFieldList RequiredFieldList indicating which columns will be needed. */ public RequiredFieldResponse pushProjection(RequiredFieldList requiredFieldList) throws FrontendException; public static class RequiredField implements Serializable { private static final long serialVersionUID = 1L; // will hold name of the field (would be null if not supplied) private String alias; // will hold the index (position) of the required field (would be -1 if not supplied), index is 0 based private int index; // A list of sub fields in this field (this could be a list of hash keys for example). // This would be null if the entire field is required and no specific sub fields are required. // In the initial implementation only one level of subfields will be populated. private List<RequiredField> subFields; // Type of this field - the value could be any current PIG DataType (as specified by the constants in DataType class). private byte type; public RequiredField() { // to allow piece-meal construction } /** * @param alias * @param index * @param subFields * @param type */ public RequiredField(String alias, int index, List<RequiredField> subFields, byte type) { this.alias = alias; this.index = index; this.subFields = subFields; this.type = type; } /** * @return the alias */ public String getAlias() { return alias; } /** * @return the index */ public int getIndex() { return index; } /** * @return the required sub fields. The return value is null if all * subfields are required */ public List<RequiredField> getSubFields() { return subFields; } public void setSubFields(List<RequiredField> subFields) { this.subFields = subFields; } /** * @return the type */ public byte getType() { return type; } public void setType(byte t) { type = t; } public void setIndex(int i) { index = i; } public void setAlias(String alias) { this.alias = alias; } } public static class RequiredFieldList implements Serializable { private static final long serialVersionUID = 1L; // list of Required fields, this will be null if all fields are required private List<RequiredField> fields = new ArrayList<RequiredField>(); /** * @param fields */ public RequiredFieldList(List<RequiredField> fields) { this.fields = fields; } /** * @return the required fields - this will be null if all fields are * required */ public List<RequiredField> getFields() { return fields; } public RequiredFieldList() { } public void add(RequiredField rf) { fields.add(rf); } } public static class RequiredFieldResponse { // the loader should pass true if it will return data containing // only the List of RequiredFields in that order. false if it // will return all fields in the data private boolean requiredFieldRequestHonored; public RequiredFieldResponse(boolean requiredFieldRequestHonored) { this.requiredFieldRequestHonored = requiredFieldRequestHonored; } // true if the loader will return data containing only the List of // RequiredFields in that order. false if the loader will return all // fields in the data public boolean getRequiredFieldResponse() { return requiredFieldRequestHonored; } // the loader should pass true if the it will return data containing // only the List of RequiredFields in that order. false if the it // will return all fields in the data public void setRequiredFieldResponse(boolean honored) { requiredFieldRequestHonored = honored; } } }
/** * This abstract class is used to implement functions to write records * from a dataset. * * */ public abstract class StoreFunc implements StoreFuncInterface { /** * This method is called by the Pig runtime in the front end to convert the * output location to an absolute path if the location is relative. The * StoreFunc implementation is free to choose how it converts a relative * location to an absolute location since this may depend on what the location * string represent (hdfs path or some other data source). * * * @param location location as provided in the "store" statement of the script * @param curDir the current working direction based on any "cd" statements * in the script before the "store" statement. If there are no "cd" statements * in the script, this would be the home directory - *
/user/<username>
 * @return the absolute location based on the arguments passed * @throws IOException * @throws IOException if the conversion is not possible */ @Override public String relToAbsPathForStoreLocation(String location, Path curDir) throws IOException { return LoadFunc.getAbsolutePath(location, curDir); } /** * Return the OutputFormat associated with StoreFunc. This will be called * on the front end during planning and not on the backend during * execution. * @return the {@link OutputFormat} associated with StoreFunc * @throws IOException if an exception occurs while constructing the * OutputFormat * */ public abstract OutputFormat getOutputFormat() throws IOException; /** * Communicate to the storer the location where the data needs to be stored. * The location string passed to the {@link StoreFunc} here is the * return value of {@link StoreFunc#relToAbsPathForStoreLocation(String, Path)} * This method will be called in the frontend and backend multiple times. Implementations * should bear in mind that this method is called multiple times and should * ensure there are no inconsistent side effects due to the multiple calls. * {@link #checkSchema(ResourceSchema)} will be called before any call to * {@link #setStoreLocation(String, Job)}. * * @param location Location returned by * {@link StoreFunc#relToAbsPathForStoreLocation(String, Path)} * @param job The {@link Job} object * @throws IOException if the location is not valid. */ public abstract void setStoreLocation(String location, Job job) throws IOException; /** * Set the schema for data to be stored. This will be called on the * front end during planning if the store is associated with a schema. * A Store function should implement this function to * check that a given schema is acceptable to it. For example, it * can check that the correct partition keys are included; * a storage function to be written directly to an OutputFormat can * make sure the schema will translate in a well defined way. * @param s to be checked * @throws IOException if this schema is not acceptable. It should include * a detailed error message indicating what is wrong with the schema. */ @Override public void checkSchema(ResourceSchema s) throws IOException { // default implementation is a no-op } /** * Initialize StoreFunc to write data. This will be called during * execution before the call to putNext. * @param writer RecordWriter to use. * @throws IOException if an exception occurs during initialization */ public abstract void prepareToWrite(RecordWriter writer) throws IOException; /** * Write a tuple the output stream to which this instance was * previously bound. * * @param t the tuple to store. * @throws IOException if an exception occurs during the write */ public abstract void putNext(Tuple t) throws IOException; /** * This method will be called by Pig both in the front end and back end to * pass a unique signature to the {@link StoreFunc} which it can use to store * information in the {@link UDFContext} which it needs to store between * various method invocations in the front end and back end. This method * will be called before other methods in {@link StoreFunc}. * @param signature a unique signature to identify this StoreFunc */ @Override public void setStoreFuncUDFContextSignature(String signature) { // default implementation is a no-op } /** * This method will be called by Pig if the job which contains this store * fails. Implementations can clean up output locations in this method to * ensure that no incorrect/incomplete results are left in the output location. * The implementation in {@link StoreFunc} deletes the output location if it * is a {@link FileSystem} location. * @param location Location returned by * {@link StoreFunc#relToAbsPathForStoreLocation(String, Path)} * @param job The {@link Job} object - this should be used only to obtain * cluster properties through {@link Job#getConfiguration()} and not to set/query * any runtime job information. */ @Override public void cleanupOnFailure(String location, Job job) throws IOException { cleanupOnFailureImpl(location, job); } /** * Implementation for {@link #cleanupOnFailure(String, Job)} * @param location * @param job * @throws IOException */ public static void cleanupOnFailureImpl(String location, Job job) throws IOException { FileSystem fs = FileSystem.get(job.getConfiguration()); Path path = new Path(location); if(fs.exists(path)){ fs.delete(path, true); } } }
/** * This interface defines how to write metadata related to data to be loaded. * If a given store function does not implement this interface, it will be assumed that it * is unable to record metadata about the associated data. */ public interface StoreMetadata { /** * Store statistics about the data being written. * @param job The {@link Job} object - this should be used only to obtain * cluster properties through {@link Job#getConfiguration()} and not to set/query * any runtime job information. * @throws IOException */ void storeStatistics(ResourceStatistics stats, String location, Job job) throws IOException; /** * Store schema of the data being written * @param job The {@link Job} object - this should be used only to obtain * cluster properties through {@link Job#getConfiguration()} and not to set/query * any runtime job information. * @throws IOException */ void storeSchema(ResourceSchema schema, String location, Job job) throws IOException; }
Given the uncertainly noted above under ResourceStatistics on how statistics should be stored, it is not clear that this interface makes sense.
LoadFunc and InputFormat Interaction
The Slicer and Slice interfaces duplicate much of the InputFormat and InputSplit interfaces provided by Hadoop. The current SliceWrapper helper function interacts with these slices to encode information about input sources into each InputSplit so that Pig can correctly manage which processing pipeline a tuple from a given input is assigned to. Currently load functions also duplicate much of the functionality of Hadoop's RecordReader interface. Currently load functions are provided a data stream and asked to parse both records and fields within records. RecordReader already provides the functionality to parse out records, though it always returns two values, key and value, not a tuple of any number of values. An integral part of this proposal is to change the LoadFunc to call RecordReader.getCurrentKey and getCurrentValue and then parse out fields in the tuple from that result.
Since Pig still needs to add information to InputSplits, user provided InputFormats and InputSplits cannot be used directly. Instead, the proposal is to change PigInputFormat to represent the job's InputFormat to !Hadoop and internally to handle the complexity of multiple inputs and hence multiple InputFormats. PigInputFormat will return PigSplits each of which contain an InputSplit. In addition, PigSplit will contain the necessary information to allow Pig to correctly address tuples to the correct data processing pipeline.
In order to support arbitrary Hadoop InputFormats, Pig can provide a load function, InputFormatLoader, that will take an InputFormat as a constructor argument. Only InputFormats which have zero argument constructors can be supported since Pig will try to instantiate the supplied InputFormat using reflection. When asked by Pig which InputFormat to use, it will return the one indicated by the user. Its call to getNext will then take the key and value provided by the associated RecordReader and construct a two field tuple. These types will be converted to Pig types as follows:
Pig type
In the future if Pig exposes boolean as a first class type, this would change to boolean
All others
byte array
How do we construct a byte array from arbitrary types?
Since the format of any other types are unknown to Pig and cannot be generalized, it does not make sense to provide casts from byte array to pig types via a LoadCaster. If users wish to use an InputFormat that uses types beyond these and cast them to Pig types, they can extend the InputFormatLoader and return a custom written LoadCaster that will handle casting their data types.
Currently, in addition to information regularly passed with an InputSplit, Pig also passes along additional information via the SliceWrapper (Pig's implementation of InputSplit). This includes an index (it's not clear what this is for, and there are no calls to SliceWrapper.getIndex() in the code; boy comments in code sure are nice), and exec type to indicate MR or local mode, and the list of target operators (the pipeline) for this input. These items can continue to be carried along as is in the proposed PigInputSplit.
Pig's Slice interface currently supports the following calls:
getLocations - will be replaced by InputSplit.getLocations
init - replaced by RecordReader.initialize
- getStart - see below
getLength - replaced by InputSplit.getLength
close - replaced by RecordReader.close
- getPos - see below
getProgress - replaced by RecordReader.getProgress
next - replaced by RecordReader.getCurrentKey and getCurrentValue
Positioning information in an InputSplit presents a problem. Hadoop 0.18 has a getPos call in the InputSplit, but it has been removed in 0.20. The reason is that input from files can generally be assigned a position, though it may not always be accurate, as in the bzip case. But for some input formats position may not have meaning. Even if Pig does not switch to using InputFormats it will have to deal with this issue, just as MR has.
These changes will affect the SamplableLoader interface. Currently it uses skip and getPos to move the underlying stream so that it can pick up a sample of tuples out of a block. Since it would sit atop InputFormat it would no longer have access to the underlying stream. It would be changed instead to skip a number of tuples.
However, in some places Pig needs this position information. In particular, when building an index for a merge join, Pig needs a way to mark a location in an input while building the index and then return to that position during the join. In this new proposal, the merge join index will contain filename and split index (index of the split in the List returned by InputFormat.getSplits()). The merge join code at run time will then seek to the right split in the file and process from that split on. For this to work the assumption is if we start from a split and read from there on to the last splitwe get sorted data - i.e. the splits in getSplits() is preserve ordering. Since this in general cannot be guaranteed, the proposal to handle this is to sample the first and last keys in each split and record both values in the index entry for that split. The index is then sorted based on both the first and last key. While seeking into the right file based on the join key during merge join processing, the implementation will then read the relevant splits in the right file as indicated in the index (reading the splits from the matching index entry to the last index entry).
These changes will also affect loaders that need to read a record in order to determine their schema, such as BinStorage or a JSON loader. These loaders will need to know how to read at least the first record on their own, without the benefit of the underlying InputFormat, since they will need to call this on the front end where an InputFormat has not yet been used.
In addition to opening files as part of Map-Reduce, Pig loaders also open files on the side in MR jobs. The new load interface needs to be able to open these side files as well. For this we would need to create a new instance of the appropriate InputFormat, calls getSplits, and then iterate over the split and for each split create a RecordReader and process the data returned by the RecordReader and then move to the next split.
Performance concerns.
With this proposal we are strongly encouraging users to double parse their data (since they will parse out the records and then parse those into fields). This could carry a performance penalty. Also, we are removing the ability to seek when sampling, which could also contain a performance penalty. A few thoughts on this:
We are already in the process of moving PigStorage to use LineRecordReader underneath, and we are getting a 30% speed up for doing it. This is only one case, but at least in this case double parsing is not hurting us.
If users that are writing both an InputFormat and a load function are concerned about double parsing, there is nothing stopping them from having their InputFormat track where field boundaries are and pass that information along to their loader so that they can parse in a single pass.
- For sampling, it is not clear how sever the penalty is for removing seek, since Hadoop is reading much of the information off disk into the buffers anyway, and sequential read on disk is not that much worse than seek.
All this said, before committing to this we should do some prototyping and performance testing to convince ourselves that these changes will be performance neutral.
StoreFunc and OutputFormat Interaction
In the same way that LoadFunc currently duplicates some functionality of InputFormat, StoreFunc duplicates some functionality of OutputFormat. StoreFunc will be changed to deal primarily with converting a tuple to a key value pair that can be stored by Hadoop.
To support arbitrary OutputFormats, a new storage function OutputFormatStorage could be written that will take an OutputFormat as a constructor argument. Only OutputFormats which have zero argument constructors can be supported since Pig will try to instantiate the supplied OutputFormat using reflection. Tuples to be stored by this storage function must have either one or two fields. If they have two fields, the first of will be taken to be the key, and the second the value. If they have one, the key will be set to null and the value will be taken from the single field. Data type conversion on this data will be done in the same way as noted above for InputFormatLoader.
Open Questions:
Does all this force us to switch to Hadoop for local mode as well? We aren't opposed to using Hadoop for local mode it just needs to get reasonable fast. Can we use InputFormat et. al. on local files without using the whole HDFS structure? Answer According to Hadoop documentation TextInputFormat works on local files as well as hdfs files. We may need to catch that we are in local mode and change the filename to file:// OR change to using Hadoop's local mode
How will we worked with compressed files? FileInputFormat already works with bzip and gzip compressed files, producing reasonable splits. PigStorage will be reworked to depend on FileInputFormat (or a descendant thereof, see next item) and should therefore be able to use this functionality. Currently Pig supports gz/bzip for arbitrary loadfunc/storefunc combinations. With this proposal, gz/bzip format will only be supported for load/store using PigStorage.
Implementation details and status
Current status
https://issues.apache.org/jira/browse/PIG-966 is the main JIRA to track progress. A branch -'load-store-redesign' (http://svn.apache.org/repos/asf/hadoop/pig/branches/load-store-redesign) has been created to undertake work on this proposal.
Status on Nov 2. 2009: This branch has simple load-store working for PigStorage and BinStorage. Joins on multiple inputs and multi store queries with multi query optimization also work. Some of the recent changes in the proposal above (the changes noted under Nov 2. 2009 in the Changes below) have not been incorporated. A list (may not be comprehensive) of remaining tasks is listed in a subsection below.
Notes on implementation details
This section is to document changes made at a high level to give an overall connected picture which code comments may not provide.
Changes to work with Hadoop InputFormat model
Hadoop has the notion of a single InputFormat per job. This is restrictive since Pig processes multiple inputs in the same map reduce job (in the case of Join, Union or Cogroup). This is handled by PigInputFormat which is the InputFormat Pig communicates to Hadoop as the Job's InputFormat. In PigInputFormat.getSplits(), the implementation processes each input in the following manner:
Instantiate the LoadFunc associated with the input
Make a clone of the Configuration passed in the getSplits() call and then invoke LoadFunc.setlocation() using the clone. The reason a clone is necessary here is because generally in the setlocation() method, the loadfunc would communicate the location to its underlying InputFormat. Typically InputFormats store the location into the Configuration for use in the getSplits() call. For example, FileInputFormat does this through FileInputFormat.setInputPaths(Job job, String location). We don't want updates to the Configuration for different inputs to over-write each other - hence the clone.
Call getInputFormat() on the LoadFunc and then getSplits() on the InputFormat returned. Note that the above setLocation call needs to happen *before* the getSplits() call and the getSplits() call needs to be given a JobContext built out of the "updated (with location)" cloned Configuration.
Wrap each returned InputSplit in PigSplit to store information like the list of target operators (the pipeline) for this input, the index of the split in the List of Splits returned by getSplits (this is used during merge join index creation) etc (comments in PigSplit explain the members)
The list of target operators helps pig give the tuples from an input to the correct part of the pipeline in a multi input pipeline (like in join, cogroup, union).
The other method in InputFormat is createRecordReader which needs be given a TaskAttemptContext. The Configuration present in the TaskAttemptContext needs to have any information that might have been put into it as a result of the above LoadFunc.setLocation() call. However the PigInputFormat.getSplits() method is called in the front-end by Hadoop and PigInputFormat.createRecordReader() is called in the back-end. So we would need to somehow pass a Map between input and the input specific Configuration (updated with location and other information from the relevant LoadFunc.setLocation() call) from the front end to the back-end. One way to pass this map would be in the Configuration of the JobContext passed to PigInputFormat.getSplits(). However in Hadoop 0.20.1 this Configuration present in the JobContext passed to PigInputFormat.getSplits() is a copy of the Configuration which is serialized to the backend and used to create the TaskAttemptContext passed in PigInputFormat.createRecordReader(). Hence passing the map this way is not possible. Hence we re-create the side effects of the LoadFunc.setLocation() call in PigInputFormat.getSplits() in PigInputFormat.createRecordReader() by the following sequence:
Instantiate the LoadFunc associated with input represented by the PigSplit passed into PigInputFormat.createRecordReader()
invoke LoadFunc.setLocation()
Call getInputFormat() on the LoadFunc and then createRecordReader() on the InputFormat returned. Note that the above setLocation call needs to happen *before* the createRecordReader() call and the createRecordReader() call needs to be given a TaskAttemptContext built out of the "updated (with location)" Configuration.
Wrap the RecordReader returned above in PigRecordReader class which is returned to Hadoop as the RecordReader. PigRecordReader has Text as key type (which is always sent with a null value to Hadoop since in pig, we really do not extract a key from input records) and a Tuple as a the value type (which is a tuple constructed from the input record).
Open Question: - We are hoping that LoadFunc actually sets up the input location on the conf in the setLocation() call - and then using that conf in createRecordReader() call - what if it does this in getInputFormat()?
Changes to work with Hadoop OutputFormat model
Hadoop has the notion of a single OutputFormat per job. PigOutputFormat is the class indicated by Pig as the OutputFormat for map reduce jobs compiled from pig scripts.
In PigOutputFormat.checkOutputSpecs(), the implementation iterates over !POStore(s) in the map and reduce phases and for each such store does the following:
Instantiate the StoreFunc associated with the !POStore
Make a clone of the JobContext passed in PigOutputFormat.checkOutputSpecs() call and then invoke StoreFunc.setStoreLocation() using the clone. The reason a clone is necessary here is because generally in the setStorelocation() method, the StoreFunc would communicate the location to its underlying OutputFormat. Typically OutputFormats store the location into the Configuration for use in the checkOutputSpecs() call. For example, FileOutputFormat does this through FileOutputFormat.setOutputPath(Job job, Path location). We don't want updates to the Configuration for different outputs to over-write each other - hence the clone.
Call getOutputFormat() on the StoreFunc and then checkOutputSpecs() on the OutputFormat returned. Note that the above setStoreLocation call needs to happen *before* the checkOutputSpecs() call and the checkOutputSpecs() call needs to be given the "updated (with location)" cloned JobContext.
PigOutputFormat.getOutputCommitter() returns a PigOutputCommitter object. The PigOutputCommitter internally keeps a list of OutputCommitters corresponding to OutputFormat of StoreFunc(s) in the POStore(s) in the map and reduce phases. It delegates all calls in the OutputCommitter class invoked by Hadoop to calls on the appropriate underlying committers.
The other method in OutputFormat is the getRecordWriter() method. In the single store case PigOutputFormat.getRecordWriter() does the following:
Instantiate the StoreFunc associated with single !POStore.
invoke StoreFunc.setStoreLocation()
Call getOutputFormat() on the StoreFunc and then getRecordWriter() on the OutputFormat returned. Note that the above setStoreLocation call needs to happen *before* the getRecordWriter() call and the getRecordWriter() call needs to be given a TaskAttemptContext which has the "updated (with location)" Configuration.
Wrap the RecordWriter returned above in PigRecordWriter class which is returned to Hadoop as the RecordWriter. PigRecordReader has WritableComparable as key type (which is always sent with a null value when we write, since in pig, we really do not have a key to store in the output( and a Tuple as a the value type (which is the output tuple).
For the multi query optimized multi store case, there are multiple !POStores in the same map reduce job. In this case, the data is written out in the Pig map or reduce pipeline itself through the POStore operator. Details of this can be found in http://wiki.apache.org/pig/PigMultiQueryPerformanceSpecification - "Internal Changes" section - "Store Operator" subsection. So from the pig runtime code, we never call Context.write() (which would have internally called PigRecordWriter.write()). So the handling of multi stores has not changed for writing data out for this redesign.
Mechanism to read side files
Pig needs to read side files in many places like in Merge Join, Order by, Skew join, dump etc. To facilitate doing this in an easy manner, a utility LoadFunc called ReadToEndLoader has been introduced. Though this has been implemented as a LoadFunc, the only LoadFunc method which is truly implemented is getNext(). The usage pattern is to construct an instance using the constructor which would take a reference to the true LoadFunc (which can read the side file data) and then repeatedly call getNext() till null is encountered in the return value. The implementation of ReadToEndLoader hides the actions of getting InputSplits from the underlying InputFormat and then processing each split by getting the RecordReader and processing data in the split before moving to the next.
Changes to skew join sampling (PoissonSampleLoader)
See discussion in PIG-1062 .
Problem 1: Earlier version of PoissonSampleLoader stored the size on disk as an extra last column in the sampled tuples it returned in map phase of sampling MR job. This was used in PartitionSkwewedKeys udf in the reduce stage of sampling job to compute total number of tuples using input-file-size/avg-disk-sz-from-samples . Avg-disk-sz-from-samples is not available with new loader design, because getPosition() is not there.
Solution : PoissonSampleLoader returns a special tuple with number of rows in that Map, in addition to the sampled tuples. To create this special tuple, the max row length in input sampled tuples is tracked, and a new tuple with size of max_row_length + 2 is created. And spl_tuple[max_row_length ] = "marker_string"
- spl_tuple[max_row_length + 1] = num_rows
The size of max_row_length+2 is used because the join key can be an expression, which is evaluated on the columns in tuples returned by the sampler, and the expression might expect specific data types to be present in certain (<= max_row_length) locations of the tuple. If number of tuples in sample is 0, the special tuple is not sent.
In PartitionSkwewedKeys udf in the reduce stage,the udf iterates over the tuples to find these special tuples and calculate the total number of rows.
Problem 2: PoissonSampleLoader samples 17 tuples from every set of tuples that will fit into reducer memory (see PigSkewedJoinSpec) . Let us call this number of tuples that fit into reducer memory - X. Ie we need to sample one tuple every X/17 tuples. Earlier, the number of tuples to be sampled was calculated before the tuples were read, in PoissonSampleLoader.computeSamples(..) . To get the number of samples to be sampled in a map, the formula used was = number-of-reducer-memories-needed * 17 / number-of-splits
Where - number-of-reducer-memories-needed = (total_file_size * disk_to_mem_factor)/available_reducer_heap_size
disk_to_mem_factor has default of 2.
Then PoissonSampleLoader would return sampled tuples by skipping split-size/num_samples bytes at a time.
With new loader we have to skip some number of tuples instead of bytes. But we don't have an estimate of total number of tuples in the input.
One way to work around this would be to use size of tuple in memory to estimate size of tuple in disk using above disk_to_mem_factor, then number of tuples to be skipped will be = (split-size/avg_mem_size_of_tuple)/numSamples
But the use of disk_to_mem_factor is very dubious, the real disk_to_mem_factor will vary based on compression-algorithm, data characteristics (sorting etc), and encoding.
Solution: The goal is to sample one tuple every X/17 tuples. (X = number of tuples that fit in available reducer memory).
To estimate X, we can use available_reducer_heap_size/average-tuple-mem-size.
Number of tuples skipped for every sampled tuple = 1/17 * ( available_reducer_heap_size/average-tuple-mem-size)
The average-tuple-mem-size and number-of-tuples-to-be-skippled-every-sampled-tuple is recalculated after a new tuple is sampled.
Changes to order-by sampling (RandomSampler)
Problem: With new interface, we cannot use the old approach : In each map job of the sampling MR job, divide the split-size by number of samples required to determine the number of bytes to skip after each sample. <
> With new interface, we can skip only by number of tuples not by bytes on disk.
Proposal: The goal is to sample tuples with equal probability for any tuple getting sampled (assuming number of tuples to be sampled is much smaller than total number of tuples).
If N is the number of samples required. In getNext(),allocate a buffer for N elements, populate it with the first N tuples, and continue scanning the partition. For every ith next() call, generate a random number r s.t. 0<=r<i, and if r<N insert the new tuple into our buffer at position r. This gives a nicely random sample of the tuples in the partition.
Changes to Streaming
Currently Pig streaming uses store and load functions to handle the serialization and deserialization of data between Pig and the user's executable. Based on the changes proposed in this redesign that will no longer be feasible. Hadoop's InputFormat and OutputFormat are not appropriate abstractions for communicating with an external executable.
Pig's current support for variable data formats in streaming is more extensive than Hadoop's. Conceptually users could create executables that read data from BinStorage or other non-text formats. The Pig development team are not aware of any users doing this, nor is it clear why they would choose to. Removing this functionality will make Pig's streaming implementation simpler. It also avoids shoe-horning streaming into the new load store design. (For complete details of Hadoop's streaming see http://hadoop.apache.org/common/docs/r0.20.1/streaming.html .)
I propose that Pig move to a model of using Hadoop's default streaming format, which is to expect new-line separated records, with tab being used as a field separator. Hadoop allows users to redefine the field separator, and so should Pig. This will also match the current default of using PigStorage as the (de)serializer for streaming. As before Pig should support communicating with the executable via either stdin and stdout or files. This will force a syntax change in Pig Latin. Currently, if a user wants to stream data to an executable with comma separated fields instead of tab separated fields, the syntax is:
define CMD `perl PigStreaming.pl - foo nameMap` input(stdin using PigStorage(',')) output(stdout using PigStorage(',')); A = load 'file'; B = stream B through CMD;
The syntax should change the reference to a store and load functions to PigToStream and StreamToPig functions as defined below. Thus the above would become:
define CMD `perl PigStreaming.pl - foo nameMap` input(stdin using PigStreaming(',')) output(stdout using PigStreaming(',')); A = load 'file'; B = stream B through CMD;
From an implementation viewpoint, the functionality required to write to and read from the streaming binary will be equivalent to the tuple parsing and serialization of PigStorage.getNext() and PigStorage.putNext(). While it will not be possible to use PigStorage directly every effort should be made to share this code (most likely by putting the actual code in static utility methods that can be called by each class) to avoid double code maintenance costs.
It has been suggested that we should switch to the typed bytes protocol that is available in Hadoop and Hive (see
https://issues.apache.org/jira/browse/PIG-966?focusedCommentId=12781695&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#action_12781695 ). While we cannot switch the default, we can make this streaming
connection an interface so that users can easily extend it in the future. The interface should be quite simple:
interface PigToStream { /** * Given a tuple, produce an array of bytes to be passed to the streaming * executable. */ public byte[] serialize(Tuple t) throws IOException; } interface StreamToPig { /** * Given a byte array from a streaming executable, produce a tuple. */ public Tuple deserialize(byte[]) throws IOException; /** * This will be called on the front end during planning and not on the back * end during execution. * * @return the {@link LoadCaster} associated with this object. * @throws IOException if there is an exception during LoadCaster */ public LoadCaster getLoadCaster() throws IOException; }
The default implementation of this would be as suggested above. The syntax for describing how data is (de)serialized would then stay as it currently is, except instead of giving a StoreFunc the user would specify a PigToStream, and instead of specifying a LoadFunc a StreamToPig.
Additionally, it has been noted that this change takes away the current optimization of Pig Latin scripts such as the following:
A = load 'myfile' split by 'file'; B = stream A through 'mycmd'; store B into 'outfile';
In this case Pig will optimize the query by removing the load function and replacing it with BinaryStorage, a function which simply passes the data as is to the streaming executable. It does not record or field parsing. Similarly, the store in the above script would be replaced with BinaryStorage.
We have two options to replace this. First, we could say that if a class implementing PigToStream also implements InputFormat, then Pig will drop the Load statement and use that InputFormat directly to load data and then pass the results to the stream. The same would be done with StreamToPig, OutputFormat and store. Second, we could create IdentityLoader and IdentityStreamToPig functions. IdentityLoader.getNext would return a tuple that just had one bytearray, which would be the entire record. This would then be a trivial serialization via the default PigToStream. Similarly IdentityStreamToPig would take the bytes returned by the stream and put them in a tuple of a single bytearray. The store function would then naturally translate this tuple into the underlying bytes. Functionally these are basically equivalent, since Pig would need to write code similar to the IdentityLoader etc. for the second case. So I believe the primary difference is in how it is presented to the user not the functionality or code written underneath.
Both of these approaches suffer from the problem that they assume TextInputFormat and TextOutputFormat. For any other IF/OF it will not be clear how to parse key, value pairs out of the stream data.
This optimization represents a fair amount of work. As the current optimization is not documented, it is not clear how many users are using it. Based on that I vote that we do not implement this optimization until such time as we see a need for it.
Remaining Tasks
BinStorage needs to implement LoadMetadata's getSchema() to replace current determineSchema()
- piggybank loaders/storers need to be ported
fix lineage code to use LoadCaster instead of LoadFunc
- local mode needs to be ported
PigDump needs to be ported
- POLoad needs to be ported
- Need to handle passing loadfunc specific info between different instances of loadfunc (Different instances in front end and between front end and back end - we need what is required in PIG-602) (setPartitionFilter() and pushOperators()for example needs this - these methods are called in the front end but the information passed is needed in the backend)
For ResourceSchema to be effectively used for communicating schema, we must fix the two level access issues with schema of bags in current schema before we make these changes, otherwise that same contagion will afflict us here.
- Input/Output handler code in streaming needs to be ported
- split by file will have to removed from language
- fix code with FIXME in comment relating to load-store redesign
Decide on what we should do with ReversibleLoadFunc and multiquery optimization
- Need to fix issues with bytesToBag, bytesToTuple and bytesToMap creating complex types with right schema
Address any Open Questions in this document
Sept 23 2009, Gates
Changed setURI to setLocation in LoadFunc and StoreFunc. Also changed it to throw IOException in the cases where the passed in location is not valid for this load or store mechanism.
Changed LoadSchema to ResourceSchema and LoadStatistics to ResourceStatistics
Added getPartitionKeys and setPartitionFilter to LoadMetadata
Sept 25 2009, Gates
Added allFinished call to StoreFunc
Sept 29 2009, Gates
- Added answer for open question 1. Added and answered open questions 2 and 3.
Nov 2 2009, Pradeep Kamath
In LoadFunc:
Added relativeToAbsolutePath() method in LoadFunc per http://issues.apache.org/jira/browse/PIG-879?focusedCommentId=12768818&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#action_12768818
- Changed comments in setLocation regarding the location passed - the location will now be the return value of relativeToAbsolutePath()
setLocation() now also takes a Job argument since the main purpose of this call is to an opportunity to the LoadFunc implementation to communicate the input location to underlying InputFormat. InputFormat implementations inturn seem to be storing this information inthe Job. For example, FileInputFormat has the following static method to set the input location: setInputPaths(JobConf conf, String commaSeparatedPaths) ;
Removed doneReading() method since there is already a RecordReader.close() method which will be called by Hadoop wherein all the functionality that needs to be done on completion of reading can be done.
- All methods now can throw IOException - this keeps the interface more flexible for exception cases
In LoadMetadata:
- getSchema(), getStatistics() and getPartitionKeys() methods now take a location and Configuration argument so that the implementation can use that information in returning the information requested.
In StoreFunc:
Added relToAbsPathForStoreLocation() method per http://issues.apache.org/jira/browse/PIG-879?focusedCommentId=12768818&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#action_12768818
- Methods which did not throw IOException now do so to enable exceptions in implementations
Removed doneWriting() - same functionality already present in RecordWriter.close() and OutputCommitter.commitTask()
Changed setSchema() to checkSchema since this method is called only to allow StoreFunc to check
Removed allFinished() - same functionality already present in OutputCommitter.cleanupJob()
Added a new section 'Implementation details and status'
Nov 11, Dmitriy Ryaboy
Minor clarification of meaning of mBytes in ResourceStatistics
Nov 12 2009, Thejas Nair Added sections -
Changes to order-by sampling (RandomSampler)
Changes to skew join sampling (PoissonSampleLoader)
Nov 23 2009, Gates
- Added section "Changes to Streaming"
Nov 23 2009, Dmitriy Ryaboy
updated StoreMetadata to match changes made to LoadMetadata
Nov 25 2009, Gates
- Updated section on streaming to suggest creating an interface for streaming (de)serializers rather than having only one hardwired option. Also added some thoughts on possible replacements for the current !BinaryStorage/split by file optimization.
Dec 16 2009, Richard Ding
- Updated section on streaming to reflect the current implementation.
Mar 1 2010, Pradeep Kamath
- Updated interfaces/abstract classes to reflect current state


text:
Lately it's been Google making all the changes, but the world's third largest search engine Bing has recently added the option for marketers and advertisers to view up to 50,000 keywords in Bing Ads. In the past, advertisers would have to narrow down their keyword search to a more specific ad group if they had more than 5,000 keywords. This was one of the most annoying things that advertisers made known to Bing, so it's no surprise that the change was coming.
In Bing's official announcement they included the following screenshot to show how it looks when you have 50,000 keywords as options after the new enhancement:
You can see this many keywords in the Keywords Tab at the Account and Campaign level as well as the Ad Group level. You can also choose the number of rows you want to see so that you don't have to display all 50,000 keywords at once (thankfully).
Advertisers also wanted Bing Ads user interface to be faster, which is something else that they put in place. Bing said that even with this many thousands of keywords, they should be generated to you almost immediately.
A Quick Reminder: Getting Started with Bing Ads and Finding the Keywords Tab
Of course if you want to utilize the new 50,000 keyword feature above, you have to understand how Bing works and be able to find the keyword tab. If you haven't bothered with this search engine just yet, now might be a great time to get started. I don't anticipate Google going anywhere anytime soon, but Bing can offer you data that might be able to help your Google strategy, not to mention the search engine does have 300 million unique visitors each month.
To get started with Bing Ads, simply follow these few steps:
- Visit this link and take a look around. They have quite a few options if you're new to search or if you would like to simply input your AdWords information.
- Click "Sign up for Bing Ads."
- Sign in to your account and get started.
- Once you fill in all of your information, you'll be able to see all of your different options. Click the "Keyword Tab" to find up to 50,000 keywords.
Of course, the options you have with Bing Ads extend far beyond just these four simple steps. You can read this article for more detailed information on the benefits of Bing ads, why this search engine matters to marketers (as well as to consumers), and how it all works.
What It Means to You
Although this is particularly good news for very large companies and advertisers, the new option is still great for smaller companies because they have improved the speed of their interface. It seems that Bing will be adding more advancements to their interface over the remainder of the year according to the announcement, so keep checking back!
Were you affected by this change from Bing? Are you a company that loves using Bing data and advance over Google? Let us know your story in the comment section below.
Republished by permission. Original here.
Images: Bing
The post Did You Know You Can Now Review 50,000 Keywords in Bing Ads? appeared first on Small Business Trends.
Source: Small Business Trends
Did You Know You Can Now Review 50,000 Keywords in Bing Ads?

subset: commoncrawl


text:
Passporthome buy Id Buy Want Online Online Express Fake 86wqpxqC
This article includes a list of references, but its sources remain unclear because it has insufficient inline citations. (January 2012) (Learn how and when to remove this template message)
Jason Starr
Starr in 2018
November 22, 1966
Brooklyn, New York
|novelist, screenwriter, comics writer
|Crime, Thriller, Satire
|Literary movement
|Links Hidden Dark 2019 Wiki Sites Web Deep q8w6px, To Cut Circuits 6 3 Loose 'footloose Short ' Remake With Time qZ7cXIZw
Jason Starr (born 1966) is an American author, comic book writer, and screenwriter from New York City. Starr has written numerous crime fiction novels and thrillers.
Starr's Tough Luck, a novel published in 2003, was a Barry Award Winner for Best Paperback Original and was a nominee at the 2004 Anthony Awards for Best Paperback Original.[1] Twisted City won the award for Best Paperback Original at the Go risk Hit And Million 1 Where Apps We Malicious Android High Do ZPwwR.[1]Wordpress To complete Set Guide Redirects Registration How Up zZfUxwxq Furthermore, in 2011, The Chill won the first ever Anthony Award for Best Graphic Novel.[1]
Starr is part of a literary circle that includes Ken Bruen, Daniel Woodrell, Wallace Stroby, Alan Glynn, Ed Brubaker, Lee Child, Bret Easton Ellis, Megan Abbott, Brian Azzarello, and Alison Gaylin.
- buy Want Passporthome Online Buy Online Fake Express Id Want Online buy Fake Id Express Online Passporthome Buy 1 Biography
- 2 Bibliography
- 3 References
- 4 External links
BiographyFake Id buy Passporthome Want Online Online Express Buy [editPassporthome Express Fake Id Want Buy Online buy Online ]
Jason Starr was born and raised in Brooklyn, New York. Growing up, he enjoyed sports such as baseball, tennis, and horse racing, but didn't have much interest in literature. He began writing plays and fiction in college at Binghamton University. Starr is known for his satirical urban crime novels, set mainly in the New York City area. When asked why (until The Pack) he wrote standalone novels and didn't rely on a series character he said, "New York City is my series character."
In the 1990s, Starr had several plays performed at Off-Off Broadway theater companies in New York. In 1997, Starr's first crime novel, Cold Caller, was published by No Exit Press in the U.K. In 1998, upon its American publication by W.W. Norton, Cold Caller was selected as a Publisher's Weekly First Fiction pick and was hailed by Kirkus Reviews as "just the thing for fans who miss the acid noir that Jim Thompson dispensed in The Grifters." The French edition of Cold Caller was selected as the official gift of the prestigious 813 book group. In the critical work Twentieth Century Crime Fiction, (Oxford University Press, 2005), author Lee Horsley selected Cold Caller as one of the basic texts for discussion.
Starr's second novel, Nothing Personal, about a compulsive gambler who hatches a sick kidnapping plot to pay off debts, was hailed as the best novel of the year by Bookends. Starr's third novel, Fake I.D., concerns a bouncer's desperate attempts to join a horse-owning syndicate. His fourth novel, Hard Feelings, about a computer networking salesman, trying to do deal with a horror from his past, was a "Penzler Pick" and the first ever original novel published by the prestigious American publisher, Vintage Crime/Black Lizard.
Tough Luck, Starr's fifth novel, about a young guy in Brooklyn who gets in deep with a mob figure, was an Anthony Award finalist and won the Barry Award for best paperback. Starr's sixth novel, Twisted City, about the devastating consequences a financial journalist faces when he attempts to recover a stolen wallet, was a Barry Award finalist and an Anthony Award winner. In 2006, Starr's novel Lights Out, a tale of jealousy and murder set in Brooklyn, was first published by St. Martin's Press in the U.S. and Orion in the U.K. It was hailed as one of the best crime novels of the year by Barnes and Noble.com and Bookreporter.com. That same year, Vintage Books published a collection of stories and essays on horse racing called Bloodlines: A Horse Racing Anthology, which Starr co-edited with Maggie Estep.
In 2007, Starr's thriller The Follower, called "this generation's Looking for Mr. Goodbar" by the New York Post, was first published by St. Martin's Press and Orion Books. TV/Film rights for The Follower were purchased by Lionsgate with Bret Easton Ells attached as writer. Also in 2007, Hard Case Crime published Slide, a second novel co-authored by Starr and Ken Bruen. In 2008, Hard Case published Starr and Bruen's third novel in the series, The Max. The fourth novel in the series, PIMP, was published in 2016.
Panic Attack, Starr's thriller about the aftermath of a shooting in suburban New York City, was published in 2009 by St. Martin's Press. The German/ Diogenes Verlag edition (Panik) was a major bestseller in Austria. It was optioned by David Fincher's production company Panic Pictures with Ocean's Eleven scribe Ted Griffin adapting.
In 2010, Starr's first graphic novel, The Chill, was published by Vertigo Crime, with art by Mick Bertilorenzi. Starr also wrote many comics for DC Comics (Justice, Inc.). In 2011, The Chill won the Anthony Award for Best Graphic Novel, making Starr one of only nine writers who have won multiple Anthony Awards.
In 2011, Penguin/Ace published Starr's The Pack, the first book in a new modern day werewolf series set mainly in the New York City area. The second book in the series, The Craving, was published by Penguin in June 2012.
In 2016, Starr's psychological thriller, Savage Lane was published by Polis Books. Savage Lane was also published in foreign editions, including the U.K. edition by No Exit PressCnpj And Free Jquery js Cpfcnpj Validator Cpf Brazilian Number awEqZwv and the German edition, Phantasien, by Diogenes Verlag.
Starr has collaborated several times with Irish crime writer, Ken Bruen. In 2006, the heralded American pulp publisher Card Id Worried you Promo 't Fake Us Don scannable Code UvxqqPB, published Bust. (Bust was an IMBA bestseller). In 2007, Hard Case Crime published Slide, a second novel co-authored by Starr and Bruen. In 2008, Hard Case published Starr and Bruen's third novel in the series, The Max. The fourth novel in the series, PIMP, was published in 2016. The series became known as "The Bust Quartet."
Starr has also become a prolific writers of comics and graphic novels, writing original works such as The Chill, as well as working on iconic characters such as Batman, Doc Savage, The Avenger, The Sandman for DC Comics and The Punisher and Wolverine Marvel Comics. The Chill won the 2011 Anthony Award for Best Graphic Novel. In October, 2012 Marvel launched its new ongoing series Wolverine Max, written by Starr with art by Roland Boschi. Starr's original comic The Returning launches from Boom Comics in March, 2014, with art by Andrea Mutti (The Executor, Star Wars, Noir).
For Marvel and DC related properties, Starr has written bestselling tie-in novels. Starr's Ant-Man: Natural Enemy was published in 2015 in conjunction with the hit movie: Ant-Man. Starr's novel Gotham: Dawn of Darkness, a prequel to the hit FOX TV show Gotham will be published in January, 2017.
In 2017, Polis Books will publish a multi-authored serial novel entitled Serial Killer created by Starr and edited by Starr and Chantelle Ami Osman. Contributors include Starr, Osman, Alison Gaylin, Charles Ardai, Jeffery Deaver, and Eoin Colfer.
Starr's work has been published in nine languages, including in Germany by Diogenes Verlag. Top Job (the German edition of Cold Caller) was adapted as an hour-long radio drama by Deutschland Radio. In 2006 a hardcover edition of Top Job was published as part of a popular series of crime novels (SZ Krimibibliothek) by Süddeutsche Zeitung.
- 1998 – Cold Caller – ISBN 0393317676
- 2000 – Nothing Personal – ISBN 1568581610
- 2000 – Fake I.D. – ISBN 1901982831
- 2002 – Hard Feelings – ISBN 0375727094
- 2003 – Tough Luck – ISBN 0375727116
(finalist 2004 Anthony Award for Best Paperback Original)[1]
- 2004 – Twisted City – ISBN 1400075068
(winner 2005 Anthony Award for Best Paperback Original)[1]
- 2006 – Lights Out – ISBN 978-0312359720
- 2007 – The Follower – ISBN 978-0312359744
- 2009 – Panic Attack – ISBN 978-0312387068
- 2011 – The Pack – ISBN 978-0441020089
- 2012 – The Craving – ISBN 978-1937007553
- 2015 – Ant-Man: Natural Enemy – ISBN 978-0785193234
- 2015 – Savage Lane
- 2017 – Buy Id Online Online Express Passporthome buy Want Fake Gotham: Dawn of Darkness
- 2018 - Gotham: City of Monsters
- 2018 - Fugitive Red (UK title Too Far)
Novels (co-written with Ken Bruen)[edit]
- 2006 – Bust – ISBN 978-0843955910
- 2007 – Slide – ISBN 978-0843957761
(finalist Wall Ideas On Kitchen Pinterest 16 Best Decor Images OqSBzw for Best Paperback Original)[1]
- 2008 – The Max – ISBN 978-0843959666
- 2016 – Pimp – ISBN 978-1783295692
Graphic novels[edit]Pcmag Calculator amp; for Android Ip Network com Rating Review 0q7cxHpw
- 2010 – The Chill – ISBN 978-1401212865
(winner 2011 Anthony Award for Best Graphic Novel)[1] And Tweens 12 For Atlanta Things Best Insiders Do To Teens nF6qPU
- 2015 – The Returning – ISBN 978-1-60886-493-5
Comic books[edit]
- 2009–2010 – Justice, Inc.. (in Doc Savage issues 1–9, DC Comics)
- 2010 – Sand (in JSA 80 Page Giant issue, DC Comics)
- 2011 – First Wave Special #1 (featuring The Avenger, Doc Savage, Batman; DC Comics)
- 2012 – Punisher Max (Special, Marvel Comics)
- 2012–2014 – Wolverine Max(issues 1–15; Marvel Comics)
- 2014 – The Returning (Boom Comics)
- 2018 - The Range in Where We Live (Image Comics)
Short-story collections[edit]
- 2006 – Bloodlines: An Anthology of Horse Racing (co-edited with Maggie Estep) – ISBNGetting How Beauty Ripped Off To Fake More As And Avoid zrEwz4qf 1400096952
Online Want Express buy Online Passporthome Buy Id Fake Film / TV[edit]
- 2010 – The Bully (short film) based on the short story by Jason Starr.
- 2018 – Cold Caller adapted by Starr and Clayton Jacobson, based on the novel by Starr, directed by Clayton Jacobson, Triptych Films
- 2018 - Panic Attack adapted by Ted Griffin.
- 2018 - The Follower (TBA), TV
- 2018 - Bust, eONE, TV Did How To Seals Navy Them Drugs Doc Addicted Flashback Get Issued OwnRZxAHHq
- ^ a b c d e Online Passporthome Fake Express buy Online Buy Want Id f g "Bouchercon World Mystery Convention : Anthony Awards Nominees". Bouchercon.info. 2003-10-02. Archived from the original on 2012-02-07. Retrieved 2012-04-04.
External links[edit]
- Official website
- Interview with Jason Starr conducted by Time Out New York in 2007
- Interview with Jason Starr conducted by Writer Unboxed.
- American male screenwriters
- American male novelists
- American crime fiction writers
- American comics writers
- Living people
- 1966 births
- Anthony Award winners
- Barry Award winners
- 20th-century American novelists
- 21st-century American novelists
- Writers from Brooklyn
- Binghamton University alumni
- Midwood High School alumni
- 20th-century American male writers
- 21st-century American male writers
- Novelists from New York (state)
- Screenwriters from New York (state)


text:
Quantum Mechanics: Introductory Concepts
Video podcast
Slides/Notes podcast
Licensed according to this deed.
Published on
In this section of the Quantum Mechanics class we discuss the particle-wave duality and the need for the quantization of energy to explain the black-body radiation and the photoelectric effect. We provide reading material, slides and video, which in a very illustrative way, explain the most difficult concept in quantum-mechanics: the particle-wave duality. A homework assignment, that teaches the students the quantization of the angular momentum and energy and also helps the students to better understand the photoelectric effect, is also provided;
Sponsored by
Cite this work
Researchers should cite this work as follows:
Dragica Vasileska Lecture Notes on Quantum Mechanics (www.eas.asu.edu/~vasilesk)
David K. Ferry, Quantum Mechanics for Electrical Engineers, Prentice Hall, 2006


text:
Formula 1 Store
Mercedes chiefs resolve to 'cool hot heads'
Formula 1 News - August, 2014
Aug.28 (GMM) Mercedes chiefs have resolved to cool the simmering feud between title-warring teammates Lewis Hamilton and Nico Rosberg.Germany's Bild newspaper reports that when the pair - who collided during the Belgian grand prix - came face-to-face in Germany on Wednesday for a sponsor photoshoot, they barely acknowledged each other's presence.In the few days since Sunday at Spa, the drivers have been exchanging their barbs through the media, but team bosses have reportedly now instructed Rosberg and Hamilton to quieten their dispute."Toto Wolff, Paddy Lowe and I agreed that hot heads should be cooled this week," team chairman Niki Lauda confirmed."Each word only triggers a reaction from the other. The drivers know now what responsibilities they have," he added.The explosive coming-together at Spa-Francorchamps is still the dominant topic in formula one, but the governing FIA has resisted calls to open an investigation despite Hamilton having accused Rosberg of crashing on purpose.The driver steward in Belgium, Emmanuele Pirro, has revealed to Italy's La Gazzetta dello Sport that his fellow FIA officials needed only "10 seconds" to decide against investigating the clash."There was no intention," he insisted. "Perhaps Rosberg was a little cunning and clever to try it, but in the end the main problem was what happened within the team."Alain Prost, one of the most successful F1 drivers of all time, agrees that what happened on lap 2 was just "a racing incident"."You have to remember that from the cockpit you can't see your big front wing, and every weekend we see two or three incidents just like it," he told Russia's f1news.ru."Lewis did not want to leave him more space, and Nico didn't want to leave the track and perhaps made a small mistake in assessing the situation."But he didn't do it intentionally, because the chance is much higher that you only damage your own car."Of course, the consequences were very serious for Lewis, but it was still a racing incident, albeit inflamed by the media and the fans and even the team," said Prost.Mark Webber, who until his F1 retirement had an intense rivalry with Sebastian Vettel, tipped the dispute to certainly roll into next weekend's Italian grand prix at Monza."The two of them are going into a media nightmare in Monza," the Australian told Austrian broadcaster Servus TV."The whole story is going to be replayed all over again and it won't be easy for them to concentrate on the job."They will only be paying attention to one another, as they know the constructors' title is as good as over."But Mercedes will overcome this controversy and get both titles," Webber predicted. comments powered by Disqus
If you are using Internet Explorer, make sure you set your document mode to IE 8 (Alt+8) or via F12 to see and add comments


text:
File Name :: ApplyIt WorldTime Clock (Version: 2.4)
Author :: KhemGurung
Category :: Other Download
Description ::
Hi guys,
See time and date around the world, set reminders and customize Clock with skins.
Good day to you all.
View File: ->http://chautari.wnso.org/forums/index.php?download=15
[Other Download] ApplyIt WorldTime Clock (Version: 2.4)
Started by KalluG, May 14 2005 09:41 AM
No replies to this topic
Posted 14 May 2005 - 09:41 AM
What qualities do I have that someone might envy !!.........................Khemraj Gurung.
0 user(s) are reading this topic
0 members, 0 guests, 0 anonymous users


text:
You may ask: "How's that even possible?" She is no longer paralyzed anymore—that's how! "How's that even possible?" I have no idea. The whole thing sounds pretty crazy to me, but the Dutch cyclist was apparently un-paralyzed after getting into an accident while training for the London 2012 Paralympics.
Monique van der Vorst, 27, was paralysed from the waist down and had been confined to a wheelchair for 13 years. Powering a bike with her hands, she had represented the Netherlands at the Paralympic Games and won two silver medals. But last year, after being knocked off her bike, her feet started to tingle, and within months, she was able to walk again. She now competes on a standard bicycle and was this week given one of just 11 places on a top women's professional cycling team. Her dream is to ride in the 2016 Olympics.
From the minimal background information in the article, it seems that Monique has had some pretty rotten luck up until a year ago. When she was 13, one leg was left paralyzed from the hip down as a result of nerve damage from what should have been a routine ankle operation. Then, in 2008, she was hit by a car and left completely paralyzed from the waist down. So, as they say, she was due.
While training for the 2012 London Paralympics, she was involved in another accident when she crashed with a fellow cyclist. Following the crash, her body began to spasm and she soon began to feel tingling in one foot, then another. By the end of the year, she was walking—and talking about the Olympics. Now, it is unclear what her chances actually are of making the team, but "[s]he now competes on a standard bicycle and was this week given one of just 11 places on a top women's professional cycling team."
Those associated with the team are all saying the right things and not harshing her out too much, including team spokesman, the apparently impossible to impress Luuc Eisenga. Said Eisenga of Monique's story "It seems like a miracle." What about her chances at a spot on the team? "In sport, everything is possible."
No kidding, Luuc. No kidding.
Paralysed cyclist is 'cured' by bike crash and now she hopes to take part in the Olympics [Daily Mail]


text:
The 28th DCC is now history.
Below are a few of the highlights. If you have any comments or pictures to contribute please contact us.
As was the case in 2008, we had an outstanding A/V setup. Two large screens with flamethrower projectors in the main ballroom plus two remote large screen LCD monitors and sound in the hallway and the demo room allowed keeping track of presentations wherever you might be.
Kermit Carlson, W9XA, and crew spent many hours making arrangements, setting up and operating A/V equipment. A/V equipment was provided by Ron Steinberg, K9IKZ.
Mark Thompson, WB9QZB headed up the local marketing efforts.
DVDs are now available.
In attendance:
Joe Lynch, N6CL, editor of CQ-VHF and his XYL Carol, W6CL, were in attendance with sample issues.
Gary Pearce KN4AQ recorded all the sessions and is offering a DVD set of the conference. DVDs may be ordered from his website at www.arvideonews.com.
Hap Holly, KC9RP, of the R.A.I.N. Report was in attendance Saturday and did interviews with many in attendance.
Larry Wolfgang, WR1B, QEX editor represented the ARRL and also had a SMT soldering practice table in the demonstration room.
Icom America and Kenwood were represented and had displays.
Of course the usual movers and shakers too numerous to mention were there too.
For a complete list of presentations, look here ...
You can see abstracts of the papers here.
Some of the speakers at the 28th DCC.
Pictures courtesy Gary Pearce, KN4AQ
|John Ackermann, N8UR
|Bill Brown, WB8ELK
|Bob Bruninga, WB4APR
|David Bern, W2LNX
|Rob Frohne, KL7NA
|John Hansen, W2FS
|Ken Konechy, W6HHC
|Jim Moawad, Arrow Electronics
|Brennan Price, N4QX
|John Ronan, EI7IG
|Paul Wiedemeir, KE5LKY
|Larry Wolfgang, WR1B
|Steve Bible, N7HPR
|Scott Cowling, WA2DFI


text:
David at Blogging Pro has a useful post for those wanting to switch to WordPress but who are daunted by the process. His post is My WordPress Install Process.
Similarly Rachel has a screencast of her install process – which was so simple that even I could do it!
Of course then there is the official Installing WordPress Guide


text:
Previous Lesson
Complete and continue
Songwriting Good To Great: The Business
Welcome and Overview! (3:39)
Module 1: Foundations
The Key To Finally Achieving Your Goals (10:47)
How To Get (And Stay) Disciplined (10:10)
My Evernote Songwriting Method (Part 1) (11:47)
My Evernote Songwriting Method (Part 2) (11:23)
Module 2: Setting Up The Business
Demystifying Copyright (6:07)
Protecting Your Songs (14:11)
Publishing Defined (7:18)
Understanding Revenue: Licensing and Roylaties (13:05)
The Four Steps To Creating Your Own Publishing Company (10:17)
Module 3: The Stages of Your Business and Archetypes
The Three Phases Of Your Songwriting Business (6:01)
The Four Songwriter Archetypes (10:31)
Discover Your Phase And Next Steps (Questionnaire)
Module 4: Build and Launch Your Network
Public Platform: Creating an Online Songwriter's Portfolio (11:02)
Public Platform: How To Get Attention (The Purple Music Cow) (8:38)
Public Platform: Starting and Growing Your Email List (5:15)
Public Platform: How a Fan Funnel Changes Everything (6:52)
Personal Pipeline: Creating your Dream 50 List (10:11)
Personal Pipeline: Tips and Best Practices For Reaching Out To Influencers (6:30)
Transform Your Email Inbox And Organize Your Pipeline With Streak (6:19)
Module 5: Creating Your Fan Funnel (Music Marketing 101)
A 30,000 Foot View Of Marketing (13:27)
The New Music Marketing Economy (10:06)
A Deeper Look At The Fan Funnel (7:08)
Breaking Down Some Fan Funnel Scenarios (8:51)
The Paid Traffic Fan Funnel Formula (10:06)
Module 6: Tying It All Together
Forging Partnerships (Publishing Deals And Record Deals) (15:08)
Beyond The Song (From StartUp To Success To Significance) (14:12)
The Four Steps To Creating Your Own Publishing Company
Lesson content locked
If you're already enrolled,
you'll need to login
Unlock this course! See details....


text:
- Home
- News
- Sports
- Opinion
- Obituaries
- Features
- Special Sections
- Classifieds
- Public Notices
A New Haven woman was charged May 29 with possession of controlled substance and theft by unlawful taking.
According to court records, Mary Vanessa Obryan, 57, had rented a house in Hodgenville. When she vacated, she allegedly took a butcher block valued at $850 and landscaping valued at $322.57 from the residence. She also is accused of refusing to return the house key which cost the property owner $140 to gain entrance.
The court records also state that medications prescribed to other persons were found inside the house after she moved.
If you currently subscribe or have subscribed in the past to the The LaRue County Herald News, then simply find your account number on your mailing label and enter it below.
Click the question mark below to see where your account ID appears on your mailing label.
|ZIP Code:


text:
Homemade organic apple pie is a great alternative to typical pumpkin pie at Thanksgiving. Also, apple pie works perfectly as a dessert for other holiday events and picnics too. However, when it comes to apple pie, it's important to go organic. Conventional apples are packed with more pesticides than any other fruit in the country, according to the Dirty Dozen list. Why serve up pesticides on a holiday? Keep reading to learn how to make pesticide-free organic apple pie anytime of the year.
Best Apples for Pie
Beyond organic, there are other considerations when it comes to apples for apple pie. A too juicy apple will make for an overly wet pie, a mealy apple doesn't taste great, and some apples cook up way too mushy. Granny Smith, Bramley, Jonagold, Rome, Honeycrisp, Cameo, Jonathon, Pink Lady are popular apple pie apples. Red Delicious, Golden Delicious, Galas, McIntosh and Cortland are much less popular pie apples. However, serious pie makers have been debating the apple issue for decades. When it comes down to it, choose the freshest and most local apples possible. You can experiment to see which apples you like best. For this particular pie, I used organic apples I had on hand, some juicer than others, so I did take steps to combat an overly wet pie, as I'll point out below.
Best Crust for Apple Pie
I think the best crust for apple pie is organic butter crust. The butter flavor works well with apples and because it's a softer crust, it soaks up any excess apple juice nicely. However, while in this recipe I'll be making butter crust, you can go with a crust made with organic shortening. There are pros and cons of each type of crust, most of which come down to personal preference. To learn more read organic pie crust 101.
Make Your Butter Crust First
You need to make your crust first, as it will need to chill. This will make enough dough for a top and bottom pie crust. Fill a large glass measuring cup with water and ice cubes and place it in the fridge. Cut 1 cup (2 sticks) of cold organic butter into small chunks. Place butter chunks in a small bowl, in your fridge to chill.
While your water and butter chills, combine 2 and 1/2 cups organic flour, 1 teaspoon salt and 1 tablespoon organic sugar in a large mixing bowl. Grab your chilled butter and cut it into your dry mixture with a basic pastry cutter quickly, until the mix resembles little peas or little shreds of butter-coated flour. This won't take long and it will look a bit uneven, which is in your favor. The longer you work dough, the tougher it'll be. If you can see some butter, that's fine.
Drizzle about 5 tablespoons of your icy cold water over your dough (avoid ice cubes). Use a silicone spatula to quickly incorporate the water into the flour mixture. Add about 5 to 7 more tablespoons of ice water, as needed, to create a dough that barely sticks together. Once your dough is barely holding together immediately stop incorporating water. Remember, you don't want to touch your dough too much – over-touching makes your dough tough, dry and not at all flaky.
Chill Your Pie Crust
Using your hands, gather half the dough into a ball and place it on a piece of non-bleached parchment paper. Gather the other half of the dough and do the same. Wrap your dough and place it in the fridge to chill. It's best to chill your dough for at least an hour before rolling it out.
Slice Your Apples
As your dough chills, get your apple pie filling started. Wash and peel about six cups worth of organic apples. Cut into slices or small chunks.
Get Apple Sugar & Spice Ready
In a small bowl combine 1 cup organic sugar, 2 tablespoons organic flour, 1 teaspoon organic cinnamon and a decent dash of organic nutmeg.
Coat Apples
Toss your sugar and spices in with your apple pieces to coat. Now, if you used all non-juicy apples, like Granny Smith, you're done. If you used any sort of juicy apples, such as Golden Delicious, place your apples in a colander, over a bowl and allow some of the juices to drain for a bit. This will help combat an overly juicy pie.
Get Your Bottom Crust Ready
Get one ball of dough from the fridge. Sprinkle some organic flour on a piece of parchment paper, place the ball of dough down, then sprinkle a little more flour on top.
Rolling Your Dough
Rolling on parchment is important because one, it'll help keep your dough from sticking to your table and two, it'll make transferring your rolled dough easier. Once your dough is rolled out, simply pick up the piece of parchment and flip it over into your pie plate of choice. Carefully peel back the parchment and situate your dough in the pie plate.
A Nice Round Pie
Using a slotted spoon to avoid juice at the bottom of the bowl, transfer your apples into the bottom crust, then place the pie plate back in the fridge. Whenever you're not messing with butter crust, it's got to be kept cold or it'll start melting all over your hands and everywhere else. Using six cups of organic apples will give your pie that nice mound look common to apple pie. Less will make for a flat pie while too many apple pieces means your pie filling will be harder to contain under the top crust.
Get Your Top Crust Ready
Decide how you want to handle the top crust. You can do a basic covered pie, (be sure to add steam vents) or a fancy lattice top. In any case, follow the steps noted above for rolling your dough – i.e. using the parchment paper.
How to Make a Fancy Top Pie Crust
I'm notoriously bad at making pretty pies. Taste-wise my pies are excellent. Look-wise, well, I won't win any pie awards. For this pie I did decide to go a little fancy and make a lattice top, but I'm far from the best teacher. Most of the time, I simply smoosh my bottom and top crusts together and call it a day. That said, if pretty matters to you, visit the links below to learn how to make a fancy pie crust top.
Chill & Bake Your Pie
After you get your top crust on your pie, be sure to press the edges of the top and bottom together, so apple juice doesn't leak out. Then sprinkle a little organic sugar on top for sparkle. If you made butter crust, place your pie in the fridge for a little bit to chill it. With butter crusts, any touching induces melting, so by now, your crust should be getting a little gooey and messy. Chilling the pie before baking helps avoid pools of butter in your oven (that leak from the crust).
After chilling your pie, cover the edges of your pie with recycled foil or a silicone reusable pie crust shield. Either foil or a shield will help prevent your pie edges from burning, because edges cook faster than the rest of the pie. Bake for 25 minutes in a 375 degrees oven. After 25 minutes, remove foil or shield from pie edge and bake another 25 minutes at the same temperature.
Take your pie out of the oven and allow it to cool, so that the juices can set, before you cut or eat it.


text:
Huntington Beach, Calif. (June 26, 2012)— Quiksilver crowned Daniel Glenn 2012 'King of the Groms' winner in Huntington Beach on Monday in a competition that saw some impressive surf by 64 of the top groms in the country, ages 8-16.
In addition to winning the title and a $600 cash prize, 15-year-old Glenn will also be going on a trip to the Quiksilver ProFrance to compete in the Global King of the Groms World Championships this September.
"Growing up in Florida, I had always dreamed of winning the Quiksilver King of the Groms," said Daniel Glenn. "Now that I have won in the US, I have a chance to make my dream come true by competing in France!"
The skins format competition was held in waist-to-chest high all day — glassy in the morning, with on shores in the afternoon. It was a battle until the final heat between Glenn and Davis Freud with Glenn pulling ahead in the final heat of the day with a massive victory.
Daniel Glenn will join groms from around the world in the next round of competition, when the Quiksilver King of The Groms World Championships arrive in France this Fall in conjunction with the Quiksilver Pro France.
The DC "Best Maneuver" $250 prize was given to Horoto Ohara for huge forehand Ariel to reverse.
For more information please visit www.quiksilver.com/kotg
About Quiksilver
Quiksilver is committed to providing tools for uncovering, expressing and expanding your personal style. Our aim is to foster the sense of individual expression and excitement – the stoke that is the essence of boardriding*. We're also here to spread the word because the only thing better than finding stoke issharing it.
*Boardriding is about timing and style. It's youthful, active, casual, and free flowing. There is no wrong way to ride a board. The goal is simply to learn, progress, improve, and give it your own interpretation.
Press Contact:
Kristen Gooding


text:
Including me.
But this post was genius:
Gungnir wrote:Wow. From girls' toys to black people. It's like I'm on the internet or something.
I do feel like you've been a total asshole in this thread and I am disappointed in you. I mean I know you do this shit on purpose because you seem to have a sort of chaotic-neutral sense of humour but at times (such as right now) it becomes tedious and makes you look like a fucking idiot.stubby wrote:We've been taking bets over the last couple of days on how long it would take for someone to call me on this. I lost. I said it would happen right after I banned you, and it would come from someone other than you (which was kind of a cheat on my part, since you were banned). So this is a little later than I expected, and not really as satisfying as I was thinking it would be, and I didn't even get to use the "I'm glad we had this talk" music like I wanted to. Probably if it came from IVhorseman or somebody I'd be a lot more contented. (My bet was that it'd be Natalya, but she's kind of a ringer.)


text:
Locations in Google Earth for teaching geologic mapping and map interpretation
Comments or suggestions? Contact Barbara Tewksbury (Hamilton College).
To go to the following places in Google Earth, copy and paste either the lat/lon or the place name into the Google Earth Fly-to box.
Or, you can download a kmz file of placemarks (Zip Archive 5kB Aug26 10), which includes the locations below plus placemarks for other great locations for mapping.
If you do not have Google Earth, you can download it here.
In the list below single asterisks (*) denote the images used in the take-home exam described here. Double asterisks (**) denote the extended mapping project described on the same page.