Example #1
0
        //ready to Launched status change happens by the AmazonHITTableManager


        //Completed tasks are removed from the TaskTable
        //Thus, we check if tasks are still pernding
        //if not tasks for a GUID are pending its deemed as complete
        //then save the results and chnage status to completed
        public static void processLaunchedJobs()
        {
            SatyamJobSubmissionsTableAccess jobDB = new SatyamJobSubmissionsTableAccess();
            List <string> guidList  = jobDB.getAllJobGUIDSByStatus(JobStatus.launched);
            List <string> readyList = jobDB.getAllJobGUIDSByStatus(JobStatus.ready);

            guidList.AddRange(readyList);


            SatyamTaskTableAccess taskDB = new SatyamTaskTableAccess();

            foreach (String GUID in guidList)
            {
                if (GUID == "SINGLE_OBJECT_LABLING_DEMO")
                {
                    continue;
                }
                List <int> IDList = taskDB.getAllIDsByGUID(GUID);
                if (IDList.Count == 0)
                {
                    SatyamSaveResults.SaveByGUIDRequester(GUID);
                    SatyamSaveResults.SaveByGUIDSatyam(GUID);
                    SatyamSaveAggregatedResult.SaveByGUIDRequester(GUID);
                    SatyamSaveAggregatedResult.SaveByGUIDSatyam(GUID);
                    jobDB.UpdateEntryStatus(GUID, JobStatus.completed);
                }
            }

            jobDB.close();
            taskDB.close();
        }
Example #2
0
        public static void processPreprocessedJobs()
        {
            SatyamJobSubmissionsTableAccess             jobDB      = new SatyamJobSubmissionsTableAccess();
            List <SatyamJobSubmissionsTableAccessEntry> jobEntries = jobDB.getAllEntriesByStatus(JobStatus.preprocessed);



            foreach (SatyamJobSubmissionsTableAccessEntry entry in jobEntries)
            {
                SatyamTaskGenerator.PopulateTasksIntoTaskTable(entry);
                if (TaskConstants.MTurkTaskTemplates.Contains(entry.JobTemplateType))
                {
                    jobDB.UpdateEntryStatus(entry.JobGUID, JobStatus.ready);
                }
                else
                {
                    jobDB.UpdateEntryStatus(entry.JobGUID, JobStatus.launched);
                }
            }
            jobDB.close();
        }
Example #3
0
        //goes through the jobDB and finds submitted jobs
        //uses the TaskGenerator to populate the taskTable


        //public static string processSubmittedJobsDebug()
        //{
        //    string debugString = "Entered the Function\n";

        //    SatyamJobSubmissionsTableAccess jobDB = new SatyamJobSubmissionsTableAccess();
        //    List<SatyamJobSubmissionsTableAccessEntry> jobEntries = jobDB.getAllEntriesByStatus(JobStatus.submitted);

        //    debugString += "got the job entries, there are " + jobEntries.Count + "\n";


        //    if (jobEntries.Count == 0)
        //    {
        //        debugString += "No new Entries in the DB\n";
        //        return debugString;
        //    }

        //    int noEntries = 0;

        //    foreach (SatyamJobSubmissionsTableAccessEntry entry in jobEntries)
        //    {
        //        debugString += "About To Populate Entry " + noEntries + "\n";

        //        //SatyamTaskGenerator.PopulateTasksIntoTaskTable(entry);
        //        debugString += SatyamTaskGenerator.PopulateTasksIntoTaskTableDebug(entry);

        //        return debugString;

        //        if (TaskConstants.MTurkTaskTemplates.Contains(entry.JobTemplateType))
        //        {
        //            jobDB.UpdateEntryStatus(entry.JobGUID, JobStatus.ready);
        //        }
        //        else
        //        {
        //            jobDB.UpdateEntryStatus(entry.JobGUID, JobStatus.launched);
        //        }
        //        noEntries++;
        //    }
        //    return debugString;
        //}


        public static void preprocessSubmittedData()
        {
            SatyamJobSubmissionsTableAccess             jobDB      = new SatyamJobSubmissionsTableAccess();
            List <SatyamJobSubmissionsTableAccessEntry> jobEntries = jobDB.getAllEntriesByStatus(JobStatus.submitted);


            foreach (SatyamJobSubmissionsTableAccessEntry entry in jobEntries)
            {
                if (SatyamTaskGenerator.PreprocessSubmittedData(entry))
                {
                    jobDB.UpdateEntryStatus(entry.JobGUID, JobStatus.preprocessed);
                }
            }
            jobDB.close();
        }
Example #4
0
        // If the results were not good enough, or aggregation method changed, retargeted, users might want to reopen the job
        // All we need to do: (IN STRICT ORDER)

        //      clear all results back to inconclusive,
        //      remove all aggregated results
        //      restore the task table as it was for the guid,
        //      change the job status back to launched, and
        // WARNING:
        //      for safety, this has to be run atomically synchronously, without any parallel process. for now.
        public static void reopenJobForMoreResults(string guid)
        {
            SatyamJobSubmissionsTableAccess      jobDB    = new SatyamJobSubmissionsTableAccess();
            SatyamJobSubmissionsTableAccessEntry jobEntry = jobDB.getEntryByJobGIUD(guid);

            jobDB.close();

            if (jobEntry.JobStatus != JobStatus.completed)
            {
                Console.WriteLine("Job not completed yet!");
                return;
            }

            SatyamAggregatedResultsTableAccess aggResultDB = new SatyamAggregatedResultsTableAccess();
            bool delSuccess = aggResultDB.DeleteEntriesByGUID(guid);

            aggResultDB.close();
            if (!delSuccess)
            {
                Console.WriteLine("Delete Agg Result DB Failed");
                return;
            }

            SatyamResultsTableAccess resultDB = new SatyamResultsTableAccess();

            if (!resultDB.UpdateStatusByGUID(guid, ResultStatus.inconclusive))
            {
                Console.WriteLine("Update Result DB Failed");
                //resultDB.close();
                //return;
            }


            List <SatyamResultsTableEntry> results = resultDB.getEntriesByGUID(guid);

            resultDB.close();
            Dictionary <int, SatyamTask> taskParamsByTaskID = new Dictionary <int, SatyamTask>();

            foreach (SatyamResultsTableEntry result in results)
            {
                if (taskParamsByTaskID.ContainsKey(result.SatyamTaskTableEntryID))
                {
                    continue;
                }

                SatyamResult satyamRes = JSonUtils.ConvertJSonToObject <SatyamResult>(result.ResultString);
                SatyamTask   task      = JSonUtils.ConvertJSonToObject <SatyamTask>(satyamRes.TaskParametersString);
                taskParamsByTaskID.Add(result.SatyamTaskTableEntryID, task);
            }

            SatyamTaskTableAccess taskDB = new SatyamTaskTableAccess();

            foreach (int taskID in taskParamsByTaskID.Keys)
            {
                SatyamTask task = taskParamsByTaskID[taskID];
                SatyamJob  job  = task.jobEntry;
                bool       suc  = taskDB.AddEntryWithSpecificID(taskID, job.JobTemplateType, job.UserID, job.JobGUIDString, JSonUtils.ConvertObjectToJSon(task),
                                                                job.JobSubmitTime, job.amazonHITInformation.Price);
                if (!suc)
                {
                    Console.WriteLine("Update Task Table Failed");
                    taskDB.close();
                    return;
                }
            }
            taskDB.close();

            jobDB = new SatyamJobSubmissionsTableAccess();
            bool success = jobDB.UpdateEntryStatus(guid, JobStatus.launched);

            jobDB.close();
            if (!success)
            {
                Console.WriteLine("Update Job Entry Failed");
                return;
            }
        }
        //public static Dictionary<string, int> getRemainingHITsFinishedTasksFromResultDB(string guid, int taskPerHIT)
        //{
        //    SatyamResultsTableAccess resultDB = new SatyamResultsTableAccess();
        //    List<SatyamResultsTableEntry>  entries = resultDB.getEntriesByGUID(guid);
        //    Dictionary<string, int> noResultPerHITID = new Dictionary<string, int>();
        //    //int noFinishedHIT = 0;
        //    foreach (SatyamResultsTableEntry entry in entries)
        //    {
        //        string HITId = JSonUtils.ConvertJSonToObject<SatyamResult>(entry.ResultString).amazonInfo.HITID;
        //        if (!noResultPerHITID.ContainsKey(HITId))
        //        {
        //            noResultPerHITID.Add(HITId,1);
        //        }
        //        else
        //        {
        //            noResultPerHITID[HITId]++;
        //            //if (noResultPerHITID[HITId] == taskPerHIT)
        //            //{
        //            //    noFinishedHIT++;
        //            //}
        //        }
        //    }
        //    return noResultPerHITID;
        //}

        //makes sure that there are enough HITS in Amazon to ensure that jobs will be done
        public static void LaunchAmazonHITsFromTaskTable(int max = int.MaxValue)
        {
            //Group them by jobguids since each job can have many tasks
            Dictionary <string, List <SatyamTaskTableEntry> > TasksByGUID = OrganizeMTurkTasksByGUID();


            if (TasksByGUID == null) //there is nothing to do!!
            {
                return;
            }



            //after running the aggregator, the number of tasks  in each guid <= no of HITS pending
            //so if there are less HITS pending we launch more and if there are more we leave them alone until the job is done


            SatyamAmazonHITTableAccess hitDB = new SatyamAmazonHITTableAccess();

            SatyamJobSubmissionsTableAccess jobDB = new SatyamJobSubmissionsTableAccess();

            //now check how manyy hits are pending and launch to ensure that there are enough hits in amazon
            foreach (KeyValuePair <string, List <SatyamTaskTableEntry> > entry in TasksByGUID)
            {
                String     jobGUID = entry.Key;
                SatyamTask task    = JSonUtils.ConvertJSonToObject <SatyamTask>(entry.Value[0].TaskParametersString);
                SatyamJob  job     = task.jobEntry;

                //// filter task templates -- temporary filter
                //if (job.JobTemplateType == TaskConstants.Segmentation_Image_MTurk) continue;

                string AmazonAccessKeyID              = job.amazonHITInformation.AmazonAccessKeyID;
                string AmazonSecretAccessKeyID        = job.amazonHITInformation.AmazonSecretAccessKeyID;
                string JobTemplateType                = entry.Value[0].JobTemplateType;
                Dictionary <string, Object> hitParams = new Dictionary <string, object>();
                hitParams.Add("Title", job.amazonHITInformation.AmazonMTurkTaskTitle);
                hitParams.Add("TaskDescription", job.amazonHITInformation.AmazonMTurkTaskDescription);
                hitParams.Add("KeyWords", job.amazonHITInformation.AmazonMTurkTaskKeywords);
                hitParams.Add("Reward", job.amazonHITInformation.Price); //convert cents to dollars

                if (TaskConstants.masterGUIDs.Contains(job.JobGUIDString))
                {
                    hitParams.Add("Masters", true);
                }


                int tasksPerHIT = job.TasksPerJob;
                List <SatyamAmazonHITTableAccessEntry> hitEntries = hitDB.getAllEntriesByJobGUIDAndStatus(jobGUID, HitStatus.pending);

                // the task will be marked as submitted when the webpage exit
                int noHITsRemaining = hitEntries.Count;

                ////////////////////////// check and deal with pending stragglers, the actual hit might have expired.
                //int noStragglers = 0;
                //foreach (SatyamAmazonHITTableAccessEntry pendingEntry in hitEntries)
                //{
                //    if ((DateTime.Now - pendingEntry.CreationTime).TotalHours > 1)
                //    {
                //        // the hit will be finished in 1hr if taken by a user,
                //        // there is a higher chance that this hit have already been expired
                //        // launch more for stragglers
                //        noStragglers++;
                //    }
                //}
                //noHITsRemaining -= noStragglers;
                ///////////////////////////////

                //////////////////////////////////// the query amazon way
                //AmazonMTurkHIT hit = new AmazonMTurkHIT();
                //hit.setAccount(AmazonAccessKeyID, AmazonSecretAccessKeyID, false);

                ////an alternative without querying amazon
                ////Dictionary<string, int> noHITsFinishedTasks = getRemainingHITsFinishedTasksFromResultDB(jobGUID, tasksPerHIT);

                ////int noHITsRemaining = 0;
                //noHITsRemaining = 0;
                //int noPendingHITDone = 0;
                //foreach (SatyamAmazonHITTableAccessEntry hitEntry in hitEntries)
                //{
                //    int noTasksPending = hit.getNumTasksRemaining(hitEntry.HITID);
                //    noHITsRemaining += noTasksPending;
                //    //an alternative without querying amazon
                //    //if (noHITsFinishedTasks.ContainsKey(hitEntry.HITID) && noHITsFinishedTasks[hitEntry.HITID] == tasksPerHIT)
                //    //{
                //    //    //HIT done
                //    //    noPendingHITDone++;
                //    //}
                //}
                ////int noHITsRemainingFromResultDB = hitEntries.Count - noPendingHITDone;

                ////Console.WriteLine("Job {0}, HITS Remaining/fromDB/Pending/noTasks: {1}/{2}/{3}",
                ////    jobGUID, noHITsRemaining, noHITsRemainingFromResultDB, hitEntries.Count, TasksByGUID[jobGUID].Count);

                ////if (noHITsRemainingFromResultDB!= noHITsRemaining)
                ////{
                ////    // not gonna work, what is the hit has less tasks than tasksPerHIT??
                ////    Console.WriteLine("Database method is wrong");
                ////}
                /////////////////////////////////////////////////////////


                int NoParallelTurker = 3; // too large will make the task stale on AMT, too small will hurt latency
                int difference       = (int)Math.Ceiling((double)(TasksByGUID[jobGUID].Count * NoParallelTurker - noHITsRemaining * tasksPerHIT) / (double)tasksPerHIT);

                //int difference = 50;
                //difference *= 2; // boost for parallelism
                //difference = 10;

                //difference = Math.Min(difference, max) * NoParallelTurker;

                if (difference > 0)
                {
                    AmazonMTurkHITBatchLauncher hitLauncher = new AmazonMTurkHITBatchLauncher(AmazonAccessKeyID, AmazonSecretAccessKeyID);
                    string url    = TaskConstants.JobTemplateTypeToTaskURI[JobTemplateType];
                    double reward = job.amazonHITInformation.Price;
                    url = url + "?reward=" + reward;
                    List <string> hitIDs = null;
                    string        hitParametersString = JSonUtils.ConvertObjectToJSon <Dictionary <string, object> >(hitParams);
                    hitLauncher.LaunchBatches(url, hitParams, difference, out hitIDs);
                    if (hitIDs != null)
                    {
                        foreach (string hitID in hitIDs)
                        {
                            hitDB.AddEntry(JobTemplateType, job.UserID, hitID, job.JobGUIDString, DateTime.Now, hitParametersString, AmazonAccessKeyID, AmazonSecretAccessKeyID);
                        }
                        jobDB.UpdateEntryStatus(entry.Key, JobStatus.launched);
                    }
                }
            }
            jobDB.close();
            hitDB.close();
        }