static void remove_output_from_cache(t_session *session, char *request_uri, t_cot_type cot_type) { t_cached_object *object; char *url; int index; if ((url = make_url(session, request_uri)) == NULL) { return; } else if ((index = cache_index(url)) == -1) { free(url); return; } pthread_mutex_lock(&cache_mutex[index]); object = cache[index]; while (object != NULL) { if (object->type == cot_type) { if (strcmp(object->file, url) == 0) { if (object->in_use <= 0) { remove_from_cache(object, index); } else { object->deadline = 0; } break; } } object = object->next; } pthread_mutex_unlock(&cache_mutex[index]); free(url); }
/***********************************************************************//** * @brief Return instrument response to diffuse source * * @param[in] event Observed event. * @param[in] source Source. * @param[in] obs Observation. * @return Instrument response to diffuse source. * * Returns the instrument response to a specified diffuse source. * * The method uses a pre-computation cache to store the instrument response * for the spatial model component. The pre-computation cache is initialised * if no cache has yet been allocated, or if at the beginning of a scan over * the events, the model parameters have changed. The beginning of a scan is * defined by an event bin index of 0. ***************************************************************************/ double GCTAResponseCube::irf_diffuse(const GEvent& event, const GSource& source, const GObservation& obs) const { // Initialise IRF double irf = 0.0; // Get pointer to CTA event bin if (!event.is_bin()) { std::string msg = "The current event is not a CTA event bin. " "This method only works on binned CTA data. Please " "make sure that a CTA observation containing binned " "CTA data is provided."; throw GException::invalid_value(G_IRF_DIFFUSE, msg); } const GCTAEventBin* bin = static_cast<const GCTAEventBin*>(&event); // Get pointer to source cache. We first search the cache for a model // with the source name. If no model was found we initialise a new // cache entry for that model. Otherwise, we simply return the actual // cache entry. GCTACubeSourceDiffuse* cache(NULL); int index = cache_index(source.name()); if (index == -1) { // No cache entry was found, thus allocate and initialise a new one cache = new GCTACubeSourceDiffuse; cache->set(source.name(), *source.model(), obs); m_cache.push_back(cache); } // endif: no cache entry was found else { // Check that the cache entry is of the expected type if (m_cache[index]->code() != GCTA_CUBE_SOURCE_DIFFUSE) { std::string msg = "Cached model \""+source.name()+"\" is not " "an extended source model. This method only " "applies to extended source models."; throw GException::invalid_value(G_IRF_DIFFUSE, msg); } cache = static_cast<GCTACubeSourceDiffuse*>(m_cache[index]); } // endelse: there was a cache entry for this model // Determine IRF value irf = cache->irf(bin->ipix(), bin->ieng()); // Compile option: Check for NaN/Inf #if defined(G_NAN_CHECK) if (gammalib::is_notanumber(irf) || gammalib::is_infinite(irf)) { std::cout << "*** ERROR: GCTAResponseCube::irf_diffuse:"; std::cout << " NaN/Inf encountered"; std::cout << " irf=" << irf; std::cout << std::endl; } #endif // Return IRF value return irf; }
gboolean c2_db_cronosII_message_add (C2Mailbox *mailbox, C2Db *db) { gint mid = 0; FILE *fd; gchar *buf; C2MessageState state; /* Initialization */ if (!cache_index (mailbox)) return FALSE; _lock (mailbox); fd = mailbox->protocol.cronosII.fd; /* Get the MID */ if (mailbox->db) mid = mailbox->db->prev->prev->mid+1; if (!mid) mid = 1; db->mid = mid; fseek (fd, 0, SEEK_END); switch (db->state) { case C2_MESSAGE_READED: state = ' '; break; default: case C2_MESSAGE_UNREADED: state = 'N'; break; case C2_MESSAGE_REPLIED: state = 'R'; break; case C2_MESSAGE_FORWARDED: state = 'F'; break; } fprintf (fd, "%c\r\r%d\r%s\r%s\r%d\r%s\r%d\n", state, db->mark, db->subject, db->from, db->date, db->account, db->mid); /* Now write to its own file */ buf = g_strdup_printf ("%s" C2_HOME "%s.mbx/%d", g_get_home_dir (), mailbox->name, db->mid); if (!(fd = fopen (buf, "w"))) { g_free (buf); c2_error_object_set (GTK_OBJECT (mailbox), -errno); return FALSE; } g_free (buf); fprintf (fd, "%s\n\n%s", db->message->header, db->message->body); fclose (fd); _rewind (mailbox); _unlock (mailbox); return TRUE; }
t_cached_object *search_cache(t_session *session, char *file) { off_t size; if(file == NULL) { return NULL; } else if((size = filesize(file)) == -1) { return NULL; } int i; if((i = cache_index(file)) == -1) { return NULL; } pthread_mutex_lock(&cache_mutex[i]); t_cached_object *object = cache[i], *result = NULL; struct stat status; /*object = cache[i];*/ while(object != NULL) { if(object->size == size) { if (strcmp(object->file, file) == 0) { if(stat(file, &status) == 0) { if((object->deadline > session->time) && (status.st_mtime == object->last_changed)) { if(same_ip(&(object->last_ip), &(session->ip_address)) == false) { if((object->deadline += TIME_IN_CACHE) > (session->time + MAX_CACHE_TIMER)) { object->deadline = session->time + MAX_CACHE_TIMER; } copy_ip(&(object->last_ip), &(session->ip_address)); } object->in_use++; result = object; } else if(object->in_use <= 0) { remove_from_cache(object, i); } } else if(object->in_use <= 0) { remove_from_cache(object, i); } break; } } object = object->next; } pthread_mutex_unlock(&cache_mutex[i]); return result; }
/// Optimization for when the cache index has already been computed inline stored_type* get(const intptr_t (&vtbl)[N], size_t j) noexcept { XTL_ASSERT(vtbl[0]); // Must be a valid vtbl pointer XTL_ASSERT(vtbl[1]); // Must be a valid vtbl pointer XTL_ASSERT(j == cache_index(vtbl)); // j must be index of location where vtbl should be stored_type*& ce = cache[j]; // Location where it should be XTL_ASSERT(ce); // Since we pre-allocate all entries if (XTL_UNLIKELY(ce->vtbl[0] != vtbl[0] || ce->vtbl[1] != vtbl[1])) { // NOTE: We don't check if the entry is occupied as even when // it is not, the vtbl may be elsewhere in the cache due // to changes to k and l after update. stored_type** cv; // See if (vtbl0,vtbl1) is elsewhere in the cache for (size_t i = 0; i <= cache_mask; ++i) if (cache[i]->vtbl[0] == vtbl[0] && cache[i]->vtbl[1] == vtbl[1]) // if so ... { cv = &cache[i]; // swap it with the right position goto Swap; } // (vtbl0,vtbl1) is not in the cache if (used <= cache_mask) // there are empty slots in cache for (size_t i = 0; i <= cache_mask; ++i) if (cache[i]->vtbl[0] == 0) // find the first empty slot { XTL_ASSERT(cache[i]->vtbl[1] == 0); cache[i]->vtbl[0] = vtbl[0]; // assign vtbl to it cache[i]->vtbl[1] = vtbl[1]; // assign vtbl to it ++used; cv = &cache[i]; // swap it with the right position goto Swap; } // There are no empty slots, we return nullptr to indicate this. return 0; Swap: std::swap(ce,*cv); } return ce; }
/// Re-establishes invariant that vtbls can only be in the cache /// entry that correspond to their cache index, unless that entry /// is already taken. void put_entries_in_right_place() { for (size_t i = 0; i <= cache_mask; ++i) { size_t k = ~0; // Keeps cache index of the previous swap. while (cache[i]->vtbl[0]) // There is a valid tuple of vtbl pointers in the entry { XTL_ASSERT(cache[i]->vtbl[N-1]); // Either all 0 or all non 0 size_t j = cache_index(cache[i]->vtbl); // Index of location where it should be if (j != k && j != i) // where it should be is not where previous one was swapped to and not here { std::swap(cache[i],cache[j]); // swap current to where it should be k = j; // remember where we swapped it to } else break; } } }
static bool add_object_to_cache(t_cached_object *object) { int index; t_cached_object *search; if (object == NULL) { return false; } else if ((index = cache_index(object->file)) == -1) { return false; } pthread_mutex_lock(&cache_mutex[index]); object->prev = NULL; object->next = cache[index]; if (cache[index] != NULL) { cache[index]->prev = object; search = cache[index]; while (search != NULL) { if (strcmp(search->file, object->file) == 0) { search->deadline = 0; break; } search = search->next; } } cache[index] = object; pthread_mutex_lock(&cache_size_mutex); cache_size += object->size; pthread_mutex_unlock(&cache_size_mutex); pthread_mutex_unlock(&cache_mutex[index]); return true; }
static t_cached_object *search_cache_for_output(t_session *session, t_cot_type cot_type) { t_cached_object *object, *result = NULL; char *url; int index; if ((url = make_url(session, NULL)) == NULL) { return NULL; } else if ((index = cache_index(url)) == -1) { free(url); return NULL; } pthread_mutex_lock(&cache_mutex[index]); object = cache[index]; while (object != NULL) { if (object->type == cot_type) { if (strcmp(object->file, url) == 0) { if (object->deadline > session->time) { object->in_use++; result = object; } else if (object->in_use <= 0) { remove_from_cache(object, index); } break; } } object = object->next; } pthread_mutex_unlock(&cache_mutex[index]); free(url); return result; }
/// Main function that will be used to get a reference to the stored element. inline stored_type* get(const intptr_t (&vtbl)[N]) noexcept { size_t j = cache_index(vtbl); return get(vtbl,j); }
/// Computes cache index for current optimal offsets and cache mask. size_t cache_index(const intptr_t vtbl[N]) const { return cache_index(vtbl,optimal_shift,cache_mask); }
t_cached_object *add_to_cache(t_session *session, char *file) { t_cached_object *object; struct stat status; off_t size; int fd, i; size_t bytes_read, bytes_total = 0; if(file == NULL) { return NULL; } else if (stat(file, &status) == -1) { return NULL; } else if((size = status.st_size) == -1) { return NULL; } else if((size < session->config->cache_min_filesize) || (size > session->config->cache_max_filesize)) { return NULL; } else if(cachesize + size > session->config->cache_size) { return NULL; } else if((object = (t_cached_object*)malloc(sizeof(t_cached_object))) == NULL) { return NULL; } else if((object->file = strdup(file)) == NULL) { free(object); return NULL; } else if((object->data = (char*)malloc(size)) == NULL) { free(object->file); free(object); return NULL; } if((fd = open(file, O_RDONLY)) != -1) { while(bytes_total < size) { if((bytes_read = read(fd, object->data + bytes_total, size - bytes_total)) == -1) { if(errno != EINTR) { free(object->data); free(object->file); free(object); close(fd); return NULL; } } else { bytes_total += bytes_read; } } close(fd); } else { free(object->data); free(object->file); free(object); return NULL; } object->last_changed = status.st_mtime; object->deadline = session->time + TIME_IN_CACHE; object->size = size; object->in_use = 1; copy_ip(&(object->last_ip), &(session->ip_address)); if((i = cache_index(file)) == -1) { free(object->data); free(object->file); free(object); return NULL; } pthread_mutex_lock(&cache_mutex[i]); object->prev = NULL; object->next = cache[i]; if(cache[i] != NULL) { cache[i]->prev = object; } cache[i] = object; pthread_mutex_lock(&cachesize_mutex); cachesize += object->size; pthread_mutex_unlock(&cachesize_mutex); pthread_mutex_unlock(&cache_mutex[i]); return object; }
/** * c2_db_cronosII_load * @mailbox: Mailbox to load. * * Will load the Cronos II Mailbox. * * Return Value: * Number of loaded messages or -1 in case of error. **/ gint c2_db_cronosII_load (C2Mailbox *mailbox) { C2Db *current = NULL, *next; FILE *fd; gint position, mid; gchar c, *line, *buf; gboolean mark; time_t date; c2_return_val_if_fail_obj (mailbox, -1, C2EDATA, GTK_OBJECT (mailbox)); /* Initialization */ if (!cache_index (mailbox)) return -1; _lock (mailbox); fd = mailbox->protocol.cronosII.fd; _rewind (mailbox); /* Go through the lines */ for (position = 0;;) { if (fread (&c, 1, sizeof (gchar), fd) < 1) break; /* A D has been reached */ if (c == 'D') { /* Lets go to the next line.. */ if (!c2_fd_move_to (fd, '\n', 1, TRUE, TRUE)) break; /* .. and start again */ continue; } /* Now that we know this is an interesting line, * lets grab it. */ if (!(line = c2_fd_get_line (fd))) { c2_error_object_set (GTK_OBJECT (mailbox), c2_errno); break; } /* Create the new C2Db */ buf = c2_str_get_word (5, line, '\r'); date = atoi (buf); g_free (buf); buf = c2_str_get_word (7, line, '\r'); mid = atoi (buf); g_free (buf); mailbox->protocol.cronosII.mid = mid; buf = c2_str_get_word (2, line, '\r'); mark = atoi (buf); g_free (buf); next = c2_db_new (mailbox, mark, c2_str_get_word (3, line, '\r'), c2_str_get_word (4, line, '\r'), c2_str_get_word (6, line, '\r'), date, mid, ++position); switch (c) { default: case ' ': next->state = C2_MESSAGE_READED; break; case 'N': next->state = C2_MESSAGE_UNREADED; break; case 'R': next->state = C2_MESSAGE_REPLIED; break; case 'F': next->state = C2_MESSAGE_FORWARDED; break; } /* Append it to the list */ if (current) current->next = next; if (!mailbox->db) mailbox->db = next; current = next; } _unlock (mailbox); _rewind (mailbox); return position; }
/** * This function will go to an specific MID * in an index file. **/ static gboolean goto_mid (C2Mailbox *mailbox, gint req_mid) { gboolean found = FALSE; gint line_length; if (!cache_index (mailbox)) return FALSE; if (mailbox->protocol.cronosII.mid < req_mid) { current_mid_less_than_req_mid: /* Go through the lines */ for (;;) { gint fmid; if ((fmid = mid_in_line (mailbox, &line_length)) < 0) { found = FALSE; _rewind (mailbox); break; } if (fmid == req_mid) { found = TRUE; break; } else fseek (mailbox->protocol.cronosII.fd, line_length, SEEK_CUR); } } else if (mailbox->protocol.cronosII.mid > req_mid) { /* FIXME This is an ugly thing to do, lets change it */ _rewind (mailbox); goto current_mid_less_than_req_mid; /* Go through the lines backwards */ for (;;) { if (!c2_fd_move_to (mailbox->protocol.cronosII.fd, '\n', 1, FALSE, TRUE)) { move_error: c2_error_object_set (GTK_OBJECT (mailbox), c2_errno); found = FALSE; _rewind (mailbox); break; } else { if (!c2_fd_move_to (mailbox->protocol.cronosII.fd, '\r', 7, FALSE, FALSE)) goto move_error; if (fseek (mailbox->protocol.cronosII.fd, -1, SEEK_CUR) < 0) { c2_error_set (-errno); goto move_error; } if (mid_in_line_reverse (mailbox, &line_length) == req_mid) { found = TRUE; break; } else fseek (mailbox->protocol.cronosII.fd, -(line_length+1), SEEK_CUR); } } } else found = TRUE; return found; }