|
Packit |
b55c50 |
/*
|
|
Packit |
b55c50 |
* Copyright (c) 2020 Red Hat, Inc.
|
|
Packit |
b55c50 |
*
|
|
Packit |
b55c50 |
* This program is free software; you can redistribute it and/or
|
|
Packit |
b55c50 |
* modify it under the terms of the GNU General Public License
|
|
Packit |
b55c50 |
* as published by the Free Software Foundation; either version 2
|
|
Packit |
b55c50 |
* of the License, or (at your option) any later version.
|
|
Packit |
b55c50 |
*
|
|
Packit |
b55c50 |
* This program is distributed in the hope that it will be useful,
|
|
Packit |
b55c50 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
b55c50 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit |
b55c50 |
* GNU General Public License for more details.
|
|
Packit |
b55c50 |
*
|
|
Packit |
b55c50 |
* You should have received a copy of the GNU General Public License
|
|
Packit |
b55c50 |
* along with this program; if not, write to the Free Software
|
|
Packit |
b55c50 |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
|
Packit |
b55c50 |
* 02110-1301, USA.
|
|
Packit |
b55c50 |
*
|
|
Packit |
b55c50 |
* $Id: //eng/uds-releases/jasper/src/uds/request.h#7 $
|
|
Packit |
b55c50 |
*/
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
#ifndef REQUEST_H
|
|
Packit |
b55c50 |
#define REQUEST_H
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
#include "cacheCounters.h"
|
|
Packit |
b55c50 |
#include "common.h"
|
|
Packit |
b55c50 |
#include "compiler.h"
|
|
Packit |
b55c50 |
#include "opaqueTypes.h"
|
|
Packit |
b55c50 |
#include "threads.h"
|
|
Packit |
b55c50 |
#include "timeUtils.h"
|
|
Packit |
b55c50 |
#include "uds.h"
|
|
Packit |
b55c50 |
#include "util/funnelQueue.h"
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
/**
|
|
Packit |
b55c50 |
* RequestAction values indicate what action, command, or query is to be
|
|
Packit |
b55c50 |
* performed when processing a Request instance.
|
|
Packit |
b55c50 |
**/
|
|
Packit |
b55c50 |
typedef enum {
|
|
Packit |
b55c50 |
// Map the API's UdsCallbackType values directly to a corresponding action.
|
|
Packit |
b55c50 |
REQUEST_INDEX = UDS_POST,
|
|
Packit |
b55c50 |
REQUEST_UPDATE = UDS_UPDATE,
|
|
Packit |
b55c50 |
REQUEST_DELETE = UDS_DELETE,
|
|
Packit |
b55c50 |
REQUEST_QUERY = UDS_QUERY,
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
REQUEST_CONTROL,
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
// REQUEST_SPARSE_CACHE_BARRIER is the action for the control request used
|
|
Packit |
b55c50 |
// by localIndexRouter.
|
|
Packit |
b55c50 |
REQUEST_SPARSE_CACHE_BARRIER,
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
// REQUEST_ANNOUNCE_CHAPTER_CLOSED is the action for the control
|
|
Packit |
b55c50 |
// request used by an indexZone to signal the other zones that it
|
|
Packit |
b55c50 |
// has closed the current open chapter.
|
|
Packit |
b55c50 |
REQUEST_ANNOUNCE_CHAPTER_CLOSED,
|
|
Packit |
b55c50 |
} RequestAction;
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
/**
|
|
Packit |
b55c50 |
* The block's rough location in the index, if any.
|
|
Packit |
b55c50 |
**/
|
|
Packit |
b55c50 |
typedef enum {
|
|
Packit |
b55c50 |
/* the block doesn't exist or the location isn't available */
|
|
Packit |
b55c50 |
LOC_UNAVAILABLE,
|
|
Packit |
b55c50 |
/* if the block was found in the open chapter */
|
|
Packit |
b55c50 |
LOC_IN_OPEN_CHAPTER,
|
|
Packit |
b55c50 |
/* if the block was found in the dense part of the index */
|
|
Packit |
b55c50 |
LOC_IN_DENSE,
|
|
Packit |
b55c50 |
/* if the block was found in the sparse part of the index */
|
|
Packit |
b55c50 |
LOC_IN_SPARSE
|
|
Packit |
b55c50 |
} IndexRegion;
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
/**
|
|
Packit |
b55c50 |
* Abstract request pipeline stages, which can also be viewed as stages in the
|
|
Packit |
b55c50 |
* life-cycle of a request.
|
|
Packit |
b55c50 |
**/
|
|
Packit |
b55c50 |
typedef enum {
|
|
Packit |
b55c50 |
STAGE_TRIAGE,
|
|
Packit |
b55c50 |
STAGE_INDEX,
|
|
Packit |
b55c50 |
STAGE_CALLBACK,
|
|
Packit |
b55c50 |
} RequestStage;
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
/**
|
|
Packit |
b55c50 |
* Control message fields for the barrier messages used to coordinate the
|
|
Packit |
b55c50 |
* addition of a chapter to the sparse chapter index cache.
|
|
Packit |
b55c50 |
**/
|
|
Packit |
b55c50 |
typedef struct barrierMessageData {
|
|
Packit |
b55c50 |
/** virtual chapter number of the chapter index to add to the sparse cache */
|
|
Packit |
b55c50 |
uint64_t virtualChapter;
|
|
Packit |
b55c50 |
} BarrierMessageData;
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
/**
|
|
Packit |
b55c50 |
* Control message fields for the chapter closed messages used to inform
|
|
Packit |
b55c50 |
* lagging zones of the first zone to close a given open chapter.
|
|
Packit |
b55c50 |
**/
|
|
Packit |
b55c50 |
typedef struct chapterClosedMessageData {
|
|
Packit |
b55c50 |
/** virtual chapter number of the chapter which was closed */
|
|
Packit |
b55c50 |
uint64_t virtualChapter;
|
|
Packit |
b55c50 |
} ChapterClosedMessageData;
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
/**
|
|
Packit |
b55c50 |
* Union of the all the zone control message fields. The RequestAction field
|
|
Packit |
b55c50 |
* (or launch function argument) selects which of the members is valid.
|
|
Packit |
b55c50 |
**/
|
|
Packit |
b55c50 |
typedef union zoneMessageData {
|
|
Packit |
b55c50 |
BarrierMessageData barrier; // for REQUEST_SPARSE_CACHE_BARRIER
|
|
Packit |
b55c50 |
ChapterClosedMessageData chapterClosed; // for REQUEST_ANNOUNCE_CHAPTER_CLOSED
|
|
Packit |
b55c50 |
} ZoneMessageData;
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
typedef struct zoneMessage {
|
|
Packit |
b55c50 |
/** the index to which the message is directed */
|
|
Packit |
b55c50 |
struct index *index;
|
|
Packit |
b55c50 |
/** the message specific data */
|
|
Packit |
b55c50 |
ZoneMessageData data;
|
|
Packit |
b55c50 |
} ZoneMessage;
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
/**
|
|
Packit |
b55c50 |
* Request context for queuing throughout the uds pipeline
|
|
Packit |
b55c50 |
*
|
|
Packit |
b55c50 |
* XXX Note that the typedef for this struct defines "Request", and that this
|
|
Packit |
b55c50 |
* should therefore be "struct request". However, this conflicts with the
|
|
Packit |
b55c50 |
* Linux kernel which also has a "struct request". This is a workaround so
|
|
Packit |
b55c50 |
* that we can make upstreaming progress. The real solution is to expose
|
|
Packit |
b55c50 |
* this structure as the true "struct uds_request" and do a lot of
|
|
Packit |
b55c50 |
* renaming.
|
|
Packit |
b55c50 |
**/
|
|
Packit |
b55c50 |
struct internalRequest {
|
|
Packit |
b55c50 |
/*
|
|
Packit |
b55c50 |
* The first part of this structure must be exactly parallel to the
|
|
Packit |
b55c50 |
* UdsRequest structure, which is part of the public UDS API.
|
|
Packit |
b55c50 |
*/
|
|
Packit |
b55c50 |
UdsChunkName chunkName; // hash value
|
|
Packit |
b55c50 |
UdsChunkData oldMetadata; // metadata from index
|
|
Packit |
b55c50 |
UdsChunkData newMetadata; // metadata from request
|
|
Packit |
b55c50 |
UdsChunkCallback *callback; // callback method when complete
|
|
Packit |
b55c50 |
struct uds_index_session *session; // The public index session
|
|
Packit |
b55c50 |
UdsCallbackType type; // the type of request
|
|
Packit |
b55c50 |
int status; // success or error code for this request
|
|
Packit |
b55c50 |
bool found; // True if the block was found in index
|
|
Packit |
b55c50 |
bool update; // move record to newest chapter if found
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
/*
|
|
Packit |
b55c50 |
* The remainder of this structure is private to the UDS implementation.
|
|
Packit |
b55c50 |
*/
|
|
Packit |
b55c50 |
FunnelQueueEntry requestQueueLink; // for lock-free request queue
|
|
Packit |
b55c50 |
Request *nextRequest;
|
|
Packit |
b55c50 |
IndexRouter *router;
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
// Data for control message requests
|
|
Packit |
b55c50 |
ZoneMessage zoneMessage;
|
|
Packit |
b55c50 |
bool isControlMessage;
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
bool unbatched; // if true, must wake worker when enqueued
|
|
Packit |
b55c50 |
bool requeued;
|
|
Packit |
b55c50 |
RequestAction action; // the action for the index to perform
|
|
Packit |
b55c50 |
unsigned int zoneNumber; // the zone for this request to use
|
|
Packit |
b55c50 |
IndexRegion location; // if and where the block was found
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
bool slLocationKnown; // slow lane has determined a location
|
|
Packit |
b55c50 |
IndexRegion slLocation; // location determined by slowlane
|
|
Packit |
b55c50 |
};
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
typedef void (*RequestRestarter)(Request *);
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
/**
|
|
Packit |
b55c50 |
* Make an asynchronous control message for an index zone and enqueue it for
|
|
Packit |
b55c50 |
* processing.
|
|
Packit |
b55c50 |
*
|
|
Packit |
b55c50 |
* @param action The control action to perform
|
|
Packit |
b55c50 |
* @param message The message to send
|
|
Packit |
b55c50 |
* @param zone The zone number of the zone to receive the message
|
|
Packit |
b55c50 |
* @param router The index router responsible for handling the message
|
|
Packit |
b55c50 |
*
|
|
Packit |
b55c50 |
* @return UDS_SUCCESS or an error code
|
|
Packit |
b55c50 |
**/
|
|
Packit |
b55c50 |
int launchZoneControlMessage(RequestAction action,
|
|
Packit |
b55c50 |
ZoneMessage message,
|
|
Packit |
b55c50 |
unsigned int zone,
|
|
Packit |
b55c50 |
IndexRouter *router)
|
|
Packit |
b55c50 |
__attribute__((warn_unused_result));
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
/**
|
|
Packit |
b55c50 |
* Free an index request.
|
|
Packit |
b55c50 |
*
|
|
Packit |
b55c50 |
* @param request The request to free
|
|
Packit |
b55c50 |
**/
|
|
Packit |
b55c50 |
void freeRequest(Request *request);
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
/**
|
|
Packit |
b55c50 |
* Enqueue a request for the next stage of the pipeline. If there is more than
|
|
Packit |
b55c50 |
* one possible queue for a stage, this function uses the request to decide
|
|
Packit |
b55c50 |
* which queue should handle it.
|
|
Packit |
b55c50 |
*
|
|
Packit |
b55c50 |
* @param request The request to enqueue
|
|
Packit |
b55c50 |
* @param nextStage The next stage of the pipeline to process the request
|
|
Packit |
b55c50 |
**/
|
|
Packit |
b55c50 |
void enqueueRequest(Request *request, RequestStage nextStage);
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
/**
|
|
Packit |
b55c50 |
* A method to restart delayed requests.
|
|
Packit |
b55c50 |
*
|
|
Packit |
b55c50 |
* @param request The request to restart
|
|
Packit |
b55c50 |
**/
|
|
Packit |
b55c50 |
void restartRequest(Request *request);
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
/**
|
|
Packit |
b55c50 |
* Set the function pointer which is used to restart requests.
|
|
Packit |
b55c50 |
* This is needed by albserver code and is used as a test hook by the unit
|
|
Packit |
b55c50 |
* tests.
|
|
Packit |
b55c50 |
*
|
|
Packit |
b55c50 |
* @param restarter The function to call to restart requests.
|
|
Packit |
b55c50 |
**/
|
|
Packit |
b55c50 |
void setRequestRestarter(RequestRestarter restarter);
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
/**
|
|
Packit |
b55c50 |
* Enter the callback stage of processing for a request, notifying the waiting
|
|
Packit |
b55c50 |
* thread if the request is synchronous, freeing the request if it is an
|
|
Packit |
b55c50 |
* asynchronous control message, or placing it on the callback queue if it is
|
|
Packit |
b55c50 |
* an asynchronous client request.
|
|
Packit |
b55c50 |
*
|
|
Packit |
b55c50 |
* @param request the request which has completed execution
|
|
Packit |
b55c50 |
**/
|
|
Packit |
b55c50 |
void enterCallbackStage(Request *request);
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
/**
|
|
Packit |
b55c50 |
* Update the context statistics to reflect the successful completion of a
|
|
Packit |
b55c50 |
* client request.
|
|
Packit |
b55c50 |
*
|
|
Packit |
b55c50 |
* @param request a client request that has successfully completed execution
|
|
Packit |
b55c50 |
**/
|
|
Packit |
b55c50 |
void updateRequestContextStats(Request *request);
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
/**
|
|
Packit |
b55c50 |
* Compute the CacheProbeType value reflecting the request and page type.
|
|
Packit |
b55c50 |
*
|
|
Packit |
b55c50 |
* @param request The request being processed, or NULL
|
|
Packit |
b55c50 |
* @param isIndexPage Whether the cache probe will be for an index page
|
|
Packit |
b55c50 |
*
|
|
Packit |
b55c50 |
* @return the cache probe type enumeration
|
|
Packit |
b55c50 |
**/
|
|
Packit |
b55c50 |
static INLINE CacheProbeType cacheProbeType(Request *request,
|
|
Packit |
b55c50 |
bool isIndexPage)
|
|
Packit |
b55c50 |
{
|
|
Packit |
b55c50 |
if ((request != NULL) && request->requeued) {
|
|
Packit |
b55c50 |
return isIndexPage ? CACHE_PROBE_INDEX_RETRY : CACHE_PROBE_RECORD_RETRY;
|
|
Packit |
b55c50 |
} else {
|
|
Packit |
b55c50 |
return isIndexPage ? CACHE_PROBE_INDEX_FIRST : CACHE_PROBE_RECORD_FIRST;
|
|
Packit |
b55c50 |
}
|
|
Packit |
b55c50 |
}
|
|
Packit |
b55c50 |
#endif /* REQUEST_H */
|