/ OSX / libsecurity_cdsa_client / lib / multidldb.cpp
multidldb.cpp
  1  /*
  2   * Copyright (c) 2000-2001,2011-2012,2014 Apple Inc. All Rights Reserved.
  3   * 
  4   * The contents of this file constitute Original Code as defined in and are
  5   * subject to the Apple Public Source License Version 1.2 (the 'License').
  6   * You may not use this file except in compliance with the License. Please obtain
  7   * a copy of the License at http://www.apple.com/publicsource and read it before
  8   * using this file.
  9   * 
 10   * This Original Code and all software distributed under the License are
 11   * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
 12   * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
 13   * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
 14   * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
 15   * specific language governing rights and limitations under the License.
 16   */
 17  
 18  
 19  //
 20  // MultiDLDb implementation.
 21  //
 22  
 23  #include <security_cdsa_client/multidldb.h>
 24  #include <security_cdsa_client/securestorage.h>
 25  
 26  
 27  
 28  namespace Security
 29  {
 30  
 31  using namespace CssmClient;
 32  
 33  namespace CssmClient
 34  {
 35  
 36  //
 37  // MultiDLDbDbCursorImpl declaration
 38  //
 39  class MultiDLDbDbCursorImpl : public DbCursorImpl
 40  {
 41  public:
 42  	MultiDLDbDbCursorImpl(const MultiDLDb &parent, const CSSM_QUERY &query, Allocator &allocator);
 43  	MultiDLDbDbCursorImpl(const MultiDLDb &parent, uint32 capacity, Allocator &allocator);
 44  	virtual ~MultiDLDbDbCursorImpl();
 45  
 46  	bool next(DbAttributes *attributes, ::CssmDataContainer *data, DbUniqueRecord &uniqueId);
 47  private:
 48  	MultiDLDb multiDLDb() { return parent<MultiDLDb>(); }
 49  	void activate();
 50  	void deactivate();
 51  
 52  	MultiDLDbImpl::ListRef mListRef;
 53  	MultiDLDbImpl::List::const_iterator mNext;
 54  	MultiDLDbImpl::List::const_iterator mEnd;
 55  	DbCursor mCursor;
 56  };
 57  
 58  } // end namespace CssmClient
 59  
 60  } // end namespace Security
 61  
 62  //
 63  // MultiDLDbImpl
 64  //
 65  MultiDLDbImpl::MultiDLDbImpl(const vector<DLDbIdentifier> &list, bool useSecureStorage, const Cssm &cssm)
 66  : ObjectImpl(cssm), mListRef(list), mUseSecureStorage(useSecureStorage)
 67  {
 68  }
 69  
 70  MultiDLDbImpl::MultiDLDbImpl(const vector<DLDbIdentifier> &list, bool useSecureStorage)
 71  : ObjectImpl(Cssm::standard()), mListRef(list), mUseSecureStorage(useSecureStorage)
 72  {
 73  }
 74  
 75  MultiDLDbImpl::~MultiDLDbImpl()
 76  {
 77  	deactivate();
 78  }
 79  
 80  Db
 81  MultiDLDbImpl::database(const DLDbIdentifier &dlDbIdentifier)
 82  {
 83  	StLock<Mutex> _(mLock);
 84  	DbMap::const_iterator it = mDbMap.find(dlDbIdentifier);
 85  	if (it != mDbMap.end())
 86  		return it->second;
 87  
 88  	Module module(dlDbIdentifier.ssuid().guid(), cssm());
 89  	DL dl;
 90  	if (dlDbIdentifier.ssuid().subserviceType() & CSSM_SERVICE_CSP)
 91  	{
 92  		if (mUseSecureStorage)
 93  			dl = SSCSPDL(module);
 94  		else
 95  			dl = CSPDL(module);
 96  	}
 97  	else
 98  		dl = DL(module);
 99  
100  	dl->subserviceId(dlDbIdentifier.ssuid().subserviceId());
101  	dl->version(dlDbIdentifier.ssuid().version());
102  	Db db(dl, dlDbIdentifier.dbName());
103  	if (find(mListRef->begin(), mListRef->end(), dlDbIdentifier) != mListRef->end())
104  		mDbMap.insert(DbMap::value_type(dlDbIdentifier, db));
105  
106  	return db;
107  }
108  
109  void
110  MultiDLDbImpl::list(const vector<DLDbIdentifier> &list)
111  {
112  	StLock<Mutex> _(mLock);
113  	set<DLDbIdentifier> oldList(mListRef->begin(), mListRef->end());
114  	mListRef = ListRef(list);
115  	set<DLDbIdentifier> newList(mListRef->begin(), mListRef->end());
116  	vector<DLDbIdentifier> obsolete;
117  	back_insert_iterator<vector<DLDbIdentifier> > ii(obsolete);
118  	// Remove all db's from the map that were in oldList but are not in mListRef.
119  	set_difference(oldList.begin(), oldList.end(), newList.begin(), newList.end(), ii);
120  	for (vector<DLDbIdentifier>::const_iterator it = obsolete.begin(); it != obsolete.end(); ++it)
121  		mDbMap.erase(*it);
122  }
123  
124  DbCursorImpl *
125  MultiDLDbImpl::newDbCursor(const CSSM_QUERY &query, Allocator &allocator)
126  {
127  	return new MultiDLDbDbCursorImpl(MultiDLDb(this), query, allocator);
128  }
129  
130  DbCursorImpl *
131  MultiDLDbImpl::newDbCursor(uint32 capacity, Allocator &allocator)
132  {
133  	return new MultiDLDbDbCursorImpl(MultiDLDb(this), capacity, allocator);
134  }
135  
136  void
137  MultiDLDbImpl::activate()
138  {
139  }
140  
141  void
142  MultiDLDbImpl::deactivate()
143  {
144  	StLock<Mutex> _(mLock);
145  	mDbMap.erase(mDbMap.begin(), mDbMap.end());
146  }
147  
148  
149  //
150  // MultiDLDbDbCursorImpl
151  //
152  MultiDLDbDbCursorImpl::MultiDLDbDbCursorImpl(const MultiDLDb &parent,
153  											 const CSSM_QUERY &query, Allocator &allocator)
154  : DbCursorImpl(parent, query, allocator)
155  {
156  }
157  
158  MultiDLDbDbCursorImpl::MultiDLDbDbCursorImpl(const MultiDLDb &parent,
159  											 uint32 capacity, Allocator &allocator)
160  : DbCursorImpl(parent, capacity, allocator)
161  {
162  }
163  
164  MultiDLDbDbCursorImpl::~MultiDLDbDbCursorImpl()
165  {
166  	try
167  	{
168  		deactivate();
169  	}
170  	catch(...) {}
171  }
172  
173  bool
174  MultiDLDbDbCursorImpl::next(DbAttributes *attributes, ::CssmDataContainer *data, DbUniqueRecord &uniqueId)
175  {
176  	activate();
177  	for (;;)
178  	{
179  		if (!mCursor)
180  		{
181  			if (mNext == mEnd)
182  			{
183  				// This is how it ends.
184  				deactivate();
185  				return false;
186  			}
187  
188  			mCursor = DbCursor(multiDLDb()->database(*mNext++), *this);
189  		}
190  
191  		try
192  		{
193  			if (mCursor->next(attributes, data, uniqueId))
194  				return true;
195  		}
196  
197  		catch(const CommonError &err)
198  		{
199  			OSStatus status = err.osStatus();
200  			if(status != CSSMERR_DL_DATASTORE_DOESNOT_EXIST)
201  				throw;
202  		}
203  
204  
205  
206  		mCursor = DbCursor();
207  	}
208  }
209  
210  void
211  MultiDLDbDbCursorImpl::activate()
212  {
213      StLock<Mutex> _(mActivateMutex);
214  	if (!mActive)
215  	{
216  		mListRef = multiDLDb()->listRef();
217  		mNext = mListRef->begin();
218  		mEnd = mListRef->end();
219  		mActive = true;
220  	}
221  }
222  
223  void
224  MultiDLDbDbCursorImpl::deactivate()
225  {
226      StLock<Mutex> _(mActivateMutex);
227  	if (mActive)
228  	{
229  		mActive = false;
230  		mListRef = MultiDLDbImpl::ListRef();
231  		mNext = mEnd;
232  		mCursor = DbCursor();
233  	}
234  }
235