| /** @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) |