bool m0_mob_load(m0_interp *interp, const char *name, FILE *err) { struct loader loader = { interp, name, err, NULL, 0, NULL, 0 }; if(!mmap_file(&loader)) goto FAIL; if(!verify_header(&loader)) goto FAIL; if(!load_chunks(&loader)) goto FAIL; if(!verify_chunks(&loader)) goto FAIL; return 1; FAIL: if(loader.mapping) { bool status = m0_platform_munmap(loader.mapping, loader.size); assert(status == 1); } return 0; }
/* Restart download from incomplete ___ARESTRA___ file. This will fail if the * file is not found/corrupt/etc. */ as_bool as_download_restart (ASDownload *dl, const char *path) { if (dl->state != DOWNLOAD_NEW) { assert (dl->state == DOWNLOAD_NEW); return FALSE; } if (!path) { assert (path); return FALSE; } /* copy file path */ dl->path = strdup (path); /* set filename after __ARESTRA__prefix */ dl->filename = as_get_filename (dl->path); if (strncmp (dl->filename, AS_DOWNLOAD_INCOMPLETE_PREFIX, strlen (AS_DOWNLOAD_INCOMPLETE_PREFIX)) == 0) dl->filename += strlen (AS_DOWNLOAD_INCOMPLETE_PREFIX); /* make sure the file exists */ if (!as_file_exists (dl->path)) { AS_ERR_1 ("Incomplete file \"%s\" does not exist.", dl->path); free (dl->path); dl->path = NULL; dl->filename = NULL; return FALSE; } /* open file */ if (!(dl->fp = fopen (dl->path, "r+b"))) { AS_ERR_1 ("Unable to open download file \"%s\" for writing", dl->path); free (dl->path); dl->path = NULL; dl->filename = NULL; return FALSE; } /* read download state from file */ if (!as_downstate_load (dl)) { AS_ERR_1 ("Unable to load state for incomplete download file \"%s\"", dl->path); fclose (dl->fp); dl->fp = NULL; free (dl->path); dl->path = NULL; dl->filename = NULL; return FALSE; } AS_HEAVY_DBG_3 ("Loaded state for \"%s\", size: %u, received: %u", dl->filename, dl->size, dl->received); #ifdef HEAVY_DEBUG assert (verify_chunks (dl)); AS_HEAVY_DBG ("Chunk state after restoring download:"); dump_chunks (dl); AS_HEAVY_DBG ("Connection state after restoring download:"); dump_connections (dl); #endif /* raise callback with state set by as_downstate_load */ if (!download_set_state (dl, dl->state, TRUE)) return FALSE; /* start things off if we are in active state */ if (dl->state == DOWNLOAD_ACTIVE) download_maintain (dl); return TRUE; }
/* * The heart of the download system. It is called whenever there are new * sources, finished chunks, etc. * Merges complete chunks and tries to assign sources to inactive ones. If * there are more sources than chunks the chunks are split up. */ static void download_maintain (ASDownload *dl) { if (dl->state != DOWNLOAD_ACTIVE) { /* Must not happen. */ assert (dl->state == DOWNLOAD_ACTIVE); return; } #ifdef VERIFY_CONN_LIST /* Verify integrity of connection list */ verify_connections (dl); #endif /* Verify integrity of chunk list. */ if (!verify_chunks (dl)) { AS_ERR_1 ("Corrupted chunk list detected for \"%s\"", dl->filename); /* Fail download */ download_failed (dl); assert (0); return; } /* Clean up chunks. */ if (!consolidate_chunks (dl)) { AS_ERR_1 ("Consolidating chunks failed for \"%s\"", dl->filename); /* Fail download */ download_failed (dl); assert (0); return; } #ifdef CHUNK_DEBUG AS_HEAVY_DBG ("Chunk state after consolidating:"); dump_chunks (dl); AS_HEAVY_DBG ("Connection state after consolidating:"); dump_connections (dl); #endif /* Is the download complete? */ if (((ASDownChunk *)dl->chunks->data)->received == dl->size) { /* Download complete */ download_finished (dl); return; } /* Download not complete. Start more chunk downloads. */ if (!start_chunks (dl)) { /* This should be harmless. */ AS_WARN_1 ("Starting chunks failed for \"%s\"", dl->filename); } /* Check if we need more sources */ if (dl->conns == NULL) { /* TODO: start source search */ AS_ERR_1 ("FIXME: No more sources for \"%s\". Make me find more.", dl->filename); } }