MigrationMemoryManager.cpp 5.39 KB
Newer Older
1
2
/*
 * @project        The CERN Tape Archive (CTA)
3
 * @copyright      Copyright(C) 2003-2021 CERN
4
5
6
7
 * @license        This program is free software: you can redistribute it and/or modify
 *                 it under the terms of the GNU General Public License as published by
 *                 the Free Software Foundation, either version 3 of the License, or
 *                 (at your option) any later version.
8
 *
9
10
11
12
 *                 This program is distributed in the hope that it will be useful,
 *                 but WITHOUT ANY WARRANTY; without even the implied warranty of
 *                 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *                 GNU General Public License for more details.
13
 *
14
15
16
 *                 You should have received a copy of the GNU General Public License
 *                 along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
17
18
19

#include "castor/tape/tapeserver/daemon/MigrationMemoryManager.hpp"
#include "castor/tape/tapeserver/daemon/MemBlock.hpp"
David COME's avatar
David COME committed
20
#include "castor/tape/tapeserver/daemon/DataPipeline.hpp"
21
22
23
24
25
26
27
28
29
30

namespace castor {
namespace tape {
namespace tapeserver {
namespace daemon {

//------------------------------------------------------------------------------
// Constructor
//------------------------------------------------------------------------------
MigrationMemoryManager::MigrationMemoryManager(const size_t numberOfBlocks, 
Victor Kotlyar's avatar
Victor Kotlyar committed
31
    const size_t blockSize, cta::log::LogContext lc)
32
:
33
34
35
36
37
38
39
40
41
    m_blockCapacity(blockSize), m_totalNumberOfBlocks(0),
    m_totalMemoryAllocated(0), m_blocksProvided(0), 
    m_blocksReturned(0), m_lc(lc)
{
  for (size_t i = 0; i < numberOfBlocks; i++) {
    m_freeBlocks.push(new MemBlock(i, blockSize));
    m_totalNumberOfBlocks++;
    m_totalMemoryAllocated += blockSize;
  }
Victor Kotlyar's avatar
Victor Kotlyar committed
42
  m_lc.log(cta::log::INFO, "MigrationMemoryManager: all blocks have been created");
43
44
45
46
47
48
49
50
}

//------------------------------------------------------------------------------
// MigrationMemoryManager::~MigrationMemoryManager
//------------------------------------------------------------------------------
MigrationMemoryManager::~MigrationMemoryManager() throw() {
  // Make sure the thread is finished: this should be done by the caller,
  // who should have called waitThreads.
51
  // castor::server::Thread::wait();
52
53
  // we expect to be called after all users are finished. Just "free"
  // the memory blocks we still have.
54
  cta::threading::BlockingQueue<MemBlock*>::valueRemainingPair ret;
55
56
57
58
59
  do {
    ret = m_freeBlocks.popGetSize();
    delete ret.value;
  } while (ret.remaining > 0);

Victor Kotlyar's avatar
Victor Kotlyar committed
60
  m_lc.log(cta::log::INFO, "MigrationMemoryManager destruction : all memory blocks have been deleted");
61
62
63
64
65
}

//------------------------------------------------------------------------------
// MigrationMemoryManager::startThreads
//------------------------------------------------------------------------------
66
void MigrationMemoryManager::startThreads()  {
67
  cta::threading::Thread::start();
Victor Kotlyar's avatar
Victor Kotlyar committed
68
  m_lc.log(cta::log::INFO, "MigrationMemoryManager starting thread");
69
70
71
72
73
}

//------------------------------------------------------------------------------
// MigrationMemoryManager::waitThreads
//------------------------------------------------------------------------------
74
void MigrationMemoryManager::waitThreads()  {
75
  cta::threading::Thread::wait();
76
77
78
79
80
}

//------------------------------------------------------------------------------
// MigrationMemoryManager::addClient
//------------------------------------------------------------------------------
David COME's avatar
David COME committed
81
void MigrationMemoryManager::addClient(DataPipeline* c)
82
 {
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
  m_clientQueue.push(c);
}

//------------------------------------------------------------------------------
// MigrationMemoryManager::areBlocksAllBack
//------------------------------------------------------------------------------
bool MigrationMemoryManager::areBlocksAllBack()
throw(){
  return m_totalNumberOfBlocks == m_freeBlocks.size();
}

//------------------------------------------------------------------------------
// MigrationMemoryManager::blockCapacity
//------------------------------------------------------------------------------
size_t MigrationMemoryManager::blockCapacity() {
  return m_blockCapacity;
}

//------------------------------------------------------------------------------
// MigrationMemoryManager::finish
//------------------------------------------------------------------------------
void MigrationMemoryManager::finish()
105
 {
106
107
108
109
110
111
112
  addClient(NULL);
}

//------------------------------------------------------------------------------
// MigrationMemoryManager::releaseBlock
//------------------------------------------------------------------------------
void MigrationMemoryManager::releaseBlock(MemBlock* mb)
113
 {
114
115
116
  mb->reset();
  m_freeBlocks.push(mb);
  {
117
    cta::threading::MutexLocker ml(m_countersMutex);
118
119
120
121
122
123
124
    m_blocksReturned++;
  }
}

//------------------------------------------------------------------------------
// MigrationMemoryManager::run
//------------------------------------------------------------------------------
125
void MigrationMemoryManager::run()  {
126
  while (true) {
David COME's avatar
David COME committed
127
    DataPipeline* c = m_clientQueue.pop();
128
129
130
131
132
    // If the c is a NULL pointer, that means end of clients
    if (!c) return;
    // Spin on the the client. We rely on the fact that he will want
    // at least one block (which is the case currently)
    while (c->provideBlock(m_freeBlocks.pop())) {
133
      cta::threading::MutexLocker ml(m_countersMutex);
134
135
136
137
138
139
140
141
142
      m_blocksProvided++;
    }
  }
}

}
}
}
}