blob: 3ca74ce650b1add0285428c19e4c13bec64b0e8d [file] [log] [blame]
/** @file
A brief file description
@section license License
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#pragma once
#include "iocore/aio/AIO.h"
#include "iocore/eventsystem/Action.h"
#include "iocore/eventsystem/Continuation.h"
#include "iocore/eventsystem/Event.h"
#include "iocore/eventsystem/IOBuffer.h"
#include "iocore/eventsystem/VIO.h"
#include "iocore/cache/Cache.h"
#include "P_CacheDoc.h"
#include "Stripe.h"
#include "StripeSM.h"
#include "tscore/ink_hrtime.h"
#include "tscore/List.h"
#include "tscore/Ptr.h"
#include <cstdint>
class Stripe;
class HttpConfigAccessor;
struct CacheVC : public CacheVConnection {
CacheVC();
VIO *do_io_read(Continuation *c, int64_t nbytes, MIOBuffer *buf) override;
VIO *do_io_pread(Continuation *c, int64_t nbytes, MIOBuffer *buf, int64_t offset) override;
VIO *do_io_write(Continuation *c, int64_t nbytes, IOBufferReader *buf, bool owner = false) override;
void do_io_close(int lerrno = -1) override;
void reenable(VIO *avio) override;
void reenable_re(VIO *avio) override;
bool get_data(int i, void *data) override;
bool set_data(int i, void *data) override;
bool
is_ram_cache_hit() const override
{
ink_assert(vio.op == VIO::READ);
return f.doc_from_ram_cache;
}
int
get_header(void **ptr, int *len) override
{
if (first_buf) {
Doc *doc = reinterpret_cast<Doc *>(first_buf->data());
*ptr = doc->hdr();
*len = doc->hlen;
return 0;
}
return -1;
}
int
set_header(void *ptr, int len) override
{
header_to_write = ptr;
header_to_write_len = len;
return 0;
}
int
get_single_data(void **ptr, int *len) override
{
if (first_buf) {
Doc *doc = reinterpret_cast<Doc *>(first_buf->data());
if (doc->data_len() == doc->total_len) {
*ptr = doc->data();
*len = doc->data_len();
return 0;
}
}
return -1;
}
int
get_volume_number() const override
{
if (stripe && stripe->cache_vol) {
return stripe->cache_vol->vol_number;
}
return -1;
}
const char *
get_disk_path() const override
{
if (stripe && stripe->disk) {
return stripe->disk->path;
}
return nullptr;
}
bool
is_compressed_in_ram() const override
{
ink_assert(vio.op == VIO::READ);
return f.compressed_in_ram;
}
bool writer_done();
int calluser(int event);
int callcont(int event);
int die();
int dead(int event, Event *e);
int handleReadDone(int event, Event *e);
int handleRead(int event, Event *e);
bool load_from_ram_cache();
bool load_from_last_open_read_call();
bool load_from_aggregation_buffer();
int do_read_call(CacheKey *akey);
int handleWrite(int event, Event *e);
int handleWriteLock(int event, Event *e);
int do_write_call();
int do_write_lock();
int do_write_lock_call();
int do_sync(uint32_t target_write_serial);
int openReadClose(int event, Event *e);
int openReadReadDone(int event, Event *e);
int openReadMain(int event, Event *e);
int openReadStartEarliest(int event, Event *e);
int openReadVecWrite(int event, Event *e);
int openReadStartHead(int event, Event *e);
int openReadFromWriter(int event, Event *e);
int openReadFromWriterMain(int event, Event *e);
int openReadFromWriterFailure(int event, Event *);
int openReadChooseWriter(int event, Event *e);
int openReadDirDelete(int event, Event *e);
int openWriteCloseDir(int event, Event *e);
int openWriteCloseHeadDone(int event, Event *e);
int openWriteCloseHead(int event, Event *e);
int openWriteCloseDataDone(int event, Event *e);
int openWriteClose(int event, Event *e);
int openWriteWriteDone(int event, Event *e);
int openWriteOverwrite(int event, Event *e);
int openWriteMain(int event, Event *e);
int openWriteStartDone(int event, Event *e);
int openWriteStartBegin(int event, Event *e);
int updateVector(int event, Event *e);
int removeEvent(int event, Event *e);
int scanStripe(int event, Event *e);
int scanObject(int event, Event *e);
int scanUpdateDone(int event, Event *e);
int scanOpenWrite(int event, Event *e);
int scanRemoveDone(int event, Event *e);
int
is_io_in_progress()
{
return io.aiocb.aio_fildes != AIO_NOT_IN_PROGRESS;
}
void
set_io_not_in_progress()
{
io.aiocb.aio_fildes = AIO_NOT_IN_PROGRESS;
}
void
set_agg_write_in_progress()
{
io.aiocb.aio_fildes = AIO_AGG_WRITE_IN_PROGRESS;
}
void cancel_trigger();
int64_t get_object_size() override;
void set_http_info(CacheHTTPInfo *info) override;
void get_http_info(CacheHTTPInfo **info) override;
/** Get the fragment table.
@return The address of the start of the fragment table,
or @c nullptr if there is no fragment table.
*/
virtual HTTPInfo::FragOffset *get_frag_table();
/** Load alt pointers and do fixups if needed.
@return Length of header data used for alternates.
*/
virtual uint32_t load_http_info(CacheHTTPInfoVector *info, struct Doc *doc, RefCountObj *block_ptr = nullptr);
bool is_pread_capable() override;
bool set_pin_in_cache(time_t time_pin) override;
time_t get_pin_in_cache() override;
// number of bytes to memset to 0 in the CacheVC when we free
// it. All member variables starting from vio are memset to 0.
// This variable is initialized in CacheVC constructor.
static int size_to_init;
// Start Region A
// This set of variables are not reset when the cacheVC is freed.
// A CacheVC must set these to the correct values whenever needed
// These are variables that are always set to the correct values
// before being used by the CacheVC
CacheKey key, first_key, earliest_key, update_key;
Dir dir, earliest_dir, overwrite_dir, first_dir;
// end Region A
// Start Region B
// These variables are individually cleared or reset when the
// CacheVC is freed. All these variables must be reset/cleared
// in free_CacheVC.
Action _action;
CacheHTTPHdr request;
CacheHTTPInfoVector vector;
CacheHTTPInfo alternate;
Ptr<IOBufferData> buf;
Ptr<IOBufferData> first_buf;
Ptr<IOBufferBlock> blocks; // data available to write
Ptr<IOBufferBlock> writer_buf;
OpenDirEntry *od = nullptr;
AIOCallback io;
int alternate_index = CACHE_ALT_INDEX_DEFAULT; // preferred position in vector
LINK(CacheVC, opendir_link);
// end Region B
// Start Region C
// These variables are memset to 0 when the structure is freed.
// The size of this region is size_to_init which is initialized
// in the CacheVC constructor. It assumes that vio is the start
// of this region.
// NOTE: NOTE: NOTE: If vio is NOT the start, then CHANGE the
// size_to_init initialization
VIO vio;
CacheFragType frag_type;
CacheHTTPInfo *info;
CacheHTTPInfoVector *write_vector;
const HttpConfigAccessor *params;
int header_len; // for communicating with agg_copy
int frag_len; // for communicating with agg_copy
uint32_t write_len; // for communicating with agg_copy
uint32_t agg_len; // for communicating with aggWrite
uint32_t write_serial; // serial of the final write for SYNC
StripeSM *stripe;
Dir *last_collision;
Event *trigger;
CacheKey *read_key;
ContinuationHandler save_handler;
uint32_t pin_in_cache;
ink_hrtime start_time;
int op_type; // Index into the metrics array for this operation, rather than a CacheOpType (fewer casts)
int recursive;
int read_recursive;
int closed;
uint64_t seek_to; // pread offset
int64_t offset; // offset into 'blocks' of data to write
int64_t writer_offset; // offset of the writer for reading from a writer
int64_t length; // length of data available to write
int64_t doc_pos; // read position in 'buf'
uint64_t write_pos; // length written
uint64_t total_len; // total length written and available to write
uint64_t doc_len; // total_length (of the selected alternate for HTTP)
uint64_t update_len;
int fragment;
int scan_msec_delay;
CacheVC *write_vc;
std::string_view hostname;
int header_to_write_len;
void *header_to_write;
short writer_lock_retry;
union {
uint32_t flags;
struct {
unsigned int use_first_key : 1;
unsigned int overwrite : 1; // overwrite first_key Dir if it exists
unsigned int close_complete : 1; // WRITE_COMPLETE is final
unsigned int sync : 1; // write to be committed to durable storage before WRITE_COMPLETE
unsigned int evacuator : 1;
unsigned int single_fragment : 1;
unsigned int evac_vector : 1;
unsigned int lookup : 1;
unsigned int update : 1;
unsigned int remove : 1;
unsigned int remove_aborted_writers : 1;
unsigned int open_read_timeout : 1; // UNUSED
unsigned int data_done : 1;
unsigned int read_from_writer_called : 1;
unsigned int rewrite_resident_alt : 1;
unsigned int readers : 1;
unsigned int doc_from_ram_cache : 1;
unsigned int hit_evacuate : 1;
unsigned int compressed_in_ram : 1; // compressed state in ram cache
unsigned int allow_empty_doc : 1; // used for cache empty http document
} f;
};
// BTF optimization used to skip reading stuff in cache partition that doesn't contain any
// dir entries.
char *scan_stripe_map;
// BTF fix to handle objects that overlapped over two different reads,
// this is how much we need to back up the buffer to get the start of the overlapping object.
off_t scan_fix_buffer_offset;
// end region C
};
LINK_DEFINITION(CacheVC, opendir_link)