main entry point for writing of non-http documents
| 397 | |
| 398 | // main entry point for writing of non-http documents |
| 399 | Action * |
| 400 | Cache::open_write(Continuation *cont, const CacheKey *key, CacheFragType frag_type, int options, time_t apin_in_cache, |
| 401 | const char *hostname, int host_len) const |
| 402 | { |
| 403 | if (!CacheProcessor::IsCacheReady(frag_type)) { |
| 404 | cont->handleEvent(CACHE_EVENT_OPEN_WRITE_FAILED, reinterpret_cast<void *>(-ECACHE_NOT_READY)); |
| 405 | return ACTION_RESULT_DONE; |
| 406 | } |
| 407 | |
| 408 | ink_assert(caches[frag_type] == this); |
| 409 | |
| 410 | intptr_t res = 0; |
| 411 | CacheVC *c = new_CacheVC(cont); |
| 412 | SCOPED_MUTEX_LOCK(lock, c->mutex, this_ethread()); |
| 413 | c->vio.op = VIO::WRITE; |
| 414 | c->op_type = static_cast<int>(CacheOpType::Write); |
| 415 | c->stripe = key_to_stripe(key, hostname, host_len); |
| 416 | StripeSM *stripe = c->stripe; |
| 417 | ts::Metrics::Gauge::increment(cache_rsb.status[c->op_type].active); |
| 418 | ts::Metrics::Gauge::increment(stripe->cache_vol->vol_rsb.status[c->op_type].active); |
| 419 | c->first_key = c->key = *key; |
| 420 | c->frag_type = frag_type; |
| 421 | /* |
| 422 | The transition from single fragment document to a multi-fragment document |
| 423 | would cause a problem if the key and the first_key collide. In case of |
| 424 | a collision, old vector data could be served to HTTP. Need to avoid that. |
| 425 | Also, when evacuating a fragment, we have to decide if its the first_key |
| 426 | or the earliest_key based on the dir_tag. |
| 427 | */ |
| 428 | do { |
| 429 | rand_CacheKey(&c->key); |
| 430 | } while (DIR_MASK_TAG(c->key.slice32(2)) == DIR_MASK_TAG(c->first_key.slice32(2))); |
| 431 | c->earliest_key = c->key; |
| 432 | c->info = nullptr; |
| 433 | c->f.overwrite = (options & CACHE_WRITE_OPT_OVERWRITE) != 0; |
| 434 | c->f.close_complete = (options & CACHE_WRITE_OPT_CLOSE_COMPLETE) != 0; |
| 435 | c->f.sync = (options & CACHE_WRITE_OPT_SYNC) == CACHE_WRITE_OPT_SYNC; |
| 436 | // coverity[Y2K38_SAFETY:FALSE] |
| 437 | c->pin_in_cache = static_cast<uint32_t>(apin_in_cache); |
| 438 | |
| 439 | if ((res = c->stripe->open_write_lock(c, false, 1)) > 0) { |
| 440 | // document currently being written, abort |
| 441 | ts::Metrics::Counter::increment(cache_rsb.status[c->op_type].failure); |
| 442 | ts::Metrics::Counter::increment(stripe->cache_vol->vol_rsb.status[c->op_type].failure); |
| 443 | cont->handleEvent(CACHE_EVENT_OPEN_WRITE_FAILED, reinterpret_cast<void *>(-res)); |
| 444 | free_CacheVC(c); |
| 445 | return ACTION_RESULT_DONE; |
| 446 | } |
| 447 | if (res < 0) { |
| 448 | SET_CONTINUATION_HANDLER(c, &CacheVC::openWriteStartBegin); |
| 449 | c->trigger = CONT_SCHED_LOCK_RETRY(c); |
| 450 | return &c->_action; |
| 451 | } |
| 452 | if (!c->f.overwrite) { |
| 453 | SET_CONTINUATION_HANDLER(c, &CacheVC::openWriteMain); |
| 454 | c->callcont(CACHE_EVENT_OPEN_WRITE); |
| 455 | return ACTION_RESULT_DONE; |
| 456 | } else { |