Coverage Report

Created: 2026-10-23 06:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/trafficserver/include/proxy/http/remap/PluginFactory.h
Line
Count
Source
1
/** @file
2
3
  Functionality allowing to load all plugins from a single config reload (header).
4
5
  @section license License
6
7
  Licensed to the Apache Software Foundation (ASF) under one
8
  or more contributor license agreements.  See the NOTICE file
9
  distributed with this work for additional information
10
  regarding copyright ownership.  The ASF licenses this file
11
  to you under the Apache License, Version 2.0 (the
12
  "License"); you may not use this file except in compliance
13
  with the License.  You may obtain a copy of the License at
14
15
      http://www.apache.org/licenses/LICENSE-2.0
16
17
  Unless required by applicable law or agreed to in writing, software
18
  distributed under the License is distributed on an "AS IS" BASIS,
19
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20
  See the License for the specific language governing permissions and
21
  limitations under the License.
22
 */
23
24
#pragma once
25
26
#include <vector>
27
28
#include "swoc/IntrusiveDList.h"
29
30
#include "tscore/Ptr.h"
31
#include "proxy/http/remap/PluginDso.h"
32
#include "proxy/http/remap/RemapPluginInfo.h"
33
34
#include "tscore/ink_uuid.h"
35
#include "ts/apidefs.h"
36
37
/**
38
 * @brief Bundles plugin info + plugin instance data to be used always together.
39
 */
40
class RemapPluginInst
41
{
42
public:
43
  RemapPluginInst()                  = delete;
44
  RemapPluginInst(RemapPluginInst &) = delete;
45
  RemapPluginInst(RemapPluginInfo &plugin);
46
  ~RemapPluginInst();
47
48
  /* Used by the PluginFactory */
49
  static RemapPluginInst *init(RemapPluginInfo *plugin, int argc, char **argv, std::string &error);
50
  void                    done();
51
52
  /* Used by the traffic server core while processing requests */
53
  TSRemapStatus doRemap(TSHttpTxn rh, TSRemapRequestInfo *rri);
54
  void          osResponse(TSHttpTxn rh, int os_response_type);
55
56
  /* List used by the plugin factory */
57
  using self_type  = RemapPluginInst; ///< Self reference type.
58
  self_type *_next = nullptr;
59
  self_type *_prev = nullptr;
60
  using Linkage    = swoc::IntrusiveLinkage<self_type>;
61
62
  /* Plugin instance = the plugin info + the data returned by the init callback */
63
  RemapPluginInfo &_plugin;
64
  void            *_instance = nullptr;
65
};
66
67
/**
68
 * @brief loads plugins, instantiates and keep track of plugin instances created by this factory.
69
 *
70
 * - Handles looking through search directories to determine final plugin canonical file name to be used (called here effective
71
 * path).
72
 * - Makes sure we load each DSO only once per effective path.
73
 * - Keeps track of all loaded remap plugins and their instances.
74
 * - Maitains the notion of plugin runtime paths and makes sure every factory instance uses different runtime paths for its plugins.
75
 * - Makes sure plugin DSOs are loaded for the lifetime of the PluginFactory.
76
 *
77
 * Each plugin factory instance corresponds to a config reload, each new config file set is meant to use a new factory instance.
78
 * A notion of runtime directory is maintained to make sure the DSO library files are not erased or modified while the library are
79
 * loaded in memory and make sure if the library file is overridden with a new DSO file that the new overriding plugin's
80
 * functionality will be loaded with the next factory, it also handles some problems noticed on different OSes in handling
81
 * filesystem links and different dl library implementations.
82
 *
83
 * @note This is meant to unify the way global and remap plugins are (re)loaded (global plugin support is not implemented yet).
84
 * @note In the case of a mixed plugin, getRemapPlugin/dynamicReloadEnabled can be internally overwritten if the plugin opt out to
85
 * take part in the dynamic reload process.
86
 */
87
class PluginFactory
88
{
89
  using PluginInstList = swoc::IntrusiveDList<RemapPluginInst::Linkage>;
90
91
public:
92
  PluginFactory();
93
  virtual ~PluginFactory();
94
95
  PluginFactory &setRuntimeDir(const fs::path &runtimeDir);
96
  PluginFactory &setCompilerPath(const fs::path &compilerPath);
97
  PluginFactory &addSearchDir(const fs::path &searchDir);
98
99
  RemapPluginInst *getRemapPlugin(const fs::path &configPath, int argc, char **argv, std::string &error, bool dynamicReloadEnabled);
100
101
  virtual const char *getUuid();
102
103
  void deactivate();
104
  void indicatePreReload();
105
  void indicatePostReload(bool reloadSuccessful);
106
  void collectUsedPlugins(std::unordered_map<PluginDso *, int> &pluginUsed);
107
108
  static void cleanup(); // For startup, clean out all temporary directory we may have left from before
109
110
protected:
111
  PluginDso *findByEffectivePath(const fs::path &path, bool dynamicReloadEnabled);
112
  fs::path   getEffectivePath(const fs::path &configPath);
113
114
  std::vector<fs::path> _searchDirs;   /** @brief ordered list of search paths where we look for plugins */
115
  fs::path              _runtimeDir;   /** @brief the path where we would create a temporary copies of the plugins to load */
116
  fs::path              _compilerPath; /** @brief the compilation script to use for cripts and other non-DSO plugins */
117
118
  PluginInstList _instList;
119
120
  ATSUuid        *_uuid = nullptr;
121
  std::error_code _ec;
122
123
  static constexpr const char *const _tag = "plugin_factory"; /** @brief log tag used by this class */
124
  static const DbgCtl               &_dbg_ctl();
125
};
126
127
inline const DbgCtl &
128
PluginFactory::_dbg_ctl()
129
0
{
130
0
  static DbgCtl dc{_tag};
131
132
0
  return dc;
133
0
}