XRootD
XrdSsiShMam Class Reference

#include <XrdSsiShMam.hh>

+ Inheritance diagram for XrdSsiShMam:
+ Collaboration diagram for XrdSsiShMam:

Public Types

enum  LockType {
  ROLock = 0 ,
  RWLock = 1
}
 

Public Member Functions

 XrdSsiShMam (XrdSsiShMat::NewParms &parms)
 
 ~XrdSsiShMam ()
 
bool AddItem (void *newdata, void *olddata, const char *key, int hash, bool replace=false)
 
bool Attach (int tout, bool isrw=false)
 
bool Create (XrdSsiShMat::CRZParms &parms)
 
bool DelItem (void *data, const char *key, int hash)
 
void Detach ()
 Detach the map from the shared memory. More...
 
bool Enumerate (void *&jar)
 
bool Enumerate (void *&jar, char *&key, void *&val)
 
bool Export ()
 
bool GetItem (void *data, const char *key, int hash)
 
int Info (const char *vname, char *buff=0, int blen=0)
 
bool Resize (XrdSsiShMat::CRZParms &parms)
 
bool Sync ()
 
bool Sync (bool dosync, bool syncdo)
 
bool Sync (int syncqsz)
 
- Public Member Functions inherited from XrdSsiShMat
 XrdSsiShMat (NewParms &parms)
 Constructor (arguments the same as for New()) More...
 
virtual ~XrdSsiShMat ()
 Destructor. Warning, your destructor should call your own Detach()! More...
 

Additional Inherited Members

- Static Public Member Functions inherited from XrdSsiShMat
static XrdSsiShMatNew (NewParms &parms)
 
- Protected Attributes inherited from XrdSsiShMat
int shmHash
 
char * shmImpl
 
char * shmPath
 
char * shmType
 
int shmTypeSz
 

Detailed Description

Definition at line 37 of file XrdSsiShMam.hh.

Member Enumeration Documentation

◆ LockType

Enumerator
ROLock 
RWLock 

Definition at line 75 of file XrdSsiShMam.hh.

75 {ROLock= 0, RWLock = 1};

Constructor & Destructor Documentation

◆ XrdSsiShMam()

XrdSsiShMam::XrdSsiShMam ( XrdSsiShMat::NewParms parms)

Definition at line 218 of file XrdSsiShMam.cc.

218  : XrdSsiShMat(parms)
219 {
220 
221 // Initialize common stuff
222 //
223  shmTemp = 0;
224  shmSize = 0;
225  shmBase = 0;
226  shmFD =-1;
227  timeOut =-1;
228  lkCount = 0;
229  syncLast = 0;
230  syncOpt = 0;
231  syncQWR = 0;
232  syncQSZ = 0;
233  syncOn = false;
234  syncBase = false;
235  isRW = false;
236  lockRO = true;
237  lockRW = true;
238  reUse = false;
239  useAtomic = true;
240 
241 // Initialize r/w mutexes
242 //
243  pthread_mutex_init(&lkMutex, NULL);
244  pthread_rwlock_init(&myMutex, NULL);
245 }
XrdSsiShMat(NewParms &parms)
Constructor (arguments the same as for New())
Definition: XrdSsiShMat.hh:343

◆ ~XrdSsiShMam()

XrdSsiShMam::~XrdSsiShMam ( )
inline

Definition at line 70 of file XrdSsiShMam.hh.

70  {Detach();
71  pthread_mutex_destroy(&lkMutex);
72  pthread_rwlock_destroy(&myMutex);
73  }
void Detach()
Detach the map from the shared memory.
Definition: XrdSsiShMam.cc:618

References Detach().

+ Here is the call graph for this function:

Member Function Documentation

◆ AddItem()

bool XrdSsiShMam::AddItem ( void *  newdata,
void *  olddata,
const char *  key,
int  hash,
bool  replace = false 
)
virtual

Add an item to the shared memory table.

Parameters
newdataPointer to the data to be added.
olddataPointer to the area where the replaced data, if any, is to be placed.
keyThe key associated with the data that is to be added.
hashThe hash of the key that is to be used to lookup the key. If the value is zero, an internal hash is computed.
replaceWhen true, if the key exists, the data associated with the key is replaced. When false, if the key exists, the addition fails with errno set to EEXIST.
Returns
true The addition/replacement succeeded. If the key was actually replaced errno is set to EEXIST else it is set to 0.
false The addition/replacement failed; errno indicates reason.

Implements XrdSsiShMat.

Definition at line 251 of file XrdSsiShMam.cc.

253 {
254  XLockHelper lockInfo(this, RWLock);
255  MemItem *theItem, *prvItem, *newItem;
256  int hEnt, kLen, iOff, retEno = 0;
257 
258 // Make sure we can allocate a new item
259 //
260  if (!shmSize) {errno = ENOTCONN; return false;}
261  if (!isRW) {errno = EROFS; return false;}
262 
263 // Verify key length
264 //
265  kLen = strlen(key);
266  if (kLen > maxKLen) {errno = ENAMETOOLONG; return false;}
267 
268 // Check if we need to remap this memory (atomic tests is not needed here).
269 // We need to do this prior to file locking as the requirements may change.
270 //
271  if (verNum != SHMINFO(verNum)) ReMap(RWLock);
272 
273 // Lock the file if we have multiple writers or recycling items
274 //
275  if (lockRW && !lockInfo.FLock()) return false;
276 
277 // First try to find the item
278 //
279  hEnt = Find(theItem, prvItem, key, hash);
280 
281 // If we found it then see if we can replace it. If so and we can reuse the
282 // the item, then just update the data portion. Otherwise, we need to get a
283 // new item and replace the existing item.
284 //
285  if (hEnt)
286  {if (olddata) memcpy(olddata, ITEM_VAL(theItem), shmTypeSz);
287  if (!replace) {errno = EEXIST; return false;}
288  if (reUse)
289  {memcpy(ITEM_VAL(theItem), newdata, shmTypeSz);
290  if (syncOn) Updated(ITEM_VOF(theItem), shmTypeSz);
291  errno = EEXIST;
292  return true;
293  }
294  retEno = EEXIST;
295  }
296 
297 // Get a new item
298 //
299  if (!(newItem = NewItem())) {errno = ENOSPC; return false;}
300 
301 // Construct the new item
302 //
303  newItem->hash = hash;
304  memcpy(ITEM_VAL(newItem), newdata, shmTypeSz);
305  strcpy(ITEM_KEY(newItem), key);
306 
307 // If we are replacing an item then We need to bridge over the item we are
308 // replacing in a way that doesn't make the item disappear for other readers.
309 // Otherwise, we can patch in the new item either on the last item in the chain
310 // or directly off the table. Note that releasing the lock creates a memory
311 // fence. To understand why this this works consider the relationship between:
312 // hEnt prvItem The state of the table
313 // 0 0 Not found because index table slot is zero
314 // 0 !0 Not found in a chain of items, prvItem is the last one
315 // !0 0 Was found and is the first or only item in the chain
316 // !0 !0 Was found and is in the middle or end of the chain
317 //
318 //
319  if (hEnt) Atomic_SET(newItem->next, theItem->next); // Atomic
320  else {hEnt = (unsigned int)hash % shmSlots;
321  if (hEnt == 0) hEnt = 1;
322  SHMINFO(itemCount)++;
323  }
324 
325  iOff = SHMOFFS(newItem);
326  if (prvItem) Atomic_SET_STRICT(prvItem->next, iOff); // Atomic
327  else {SHMINFO(slotsUsed)++;
328  Atomic_SET_STRICT(shmIndex[hEnt],iOff); // Atomic
329  if (syncOn) Updated(SHMOFFS(&shmIndex[hEnt]));
330  }
331 
332 // Indicate which things we changed if we have syncing
333 //
334  if (syncOn)
335  {Updated(0);
336  Updated(SHMOFFS(newItem));
337  if (prvItem) Updated(SHMOFFS(prvItem));
338  }
339 
340 // All done, return result
341 //
342  errno = retEno;
343  return true;
344 }
#define Atomic_SET(x, y)
#define SHMOFFS(addr)
Definition: XrdSsiShMam.cc:90
#define ITEM_VOF(x)
Definition: XrdSsiShMam.cc:96
#define SHMINFO(x)
Definition: XrdSsiShMam.cc:86
#define ITEM_KEY(x)
Definition: XrdSsiShMam.cc:92
#define ITEM_VAL(x)
Definition: XrdSsiShMam.cc:94

References Atomic_SET, ITEM_KEY, ITEM_VAL, ITEM_VOF, RWLock, SHMINFO, SHMOFFS, and XrdSsiShMat::shmTypeSz.

Referenced by Resize().

+ Here is the caller graph for this function:

◆ Attach()

bool XrdSsiShMam::Attach ( int  tout,
bool  isrw = false 
)
virtual

Attach this object to the shared memory associated with this object at creation time (see New() method). The attach operation waits until the shared memory file is available. At that time, the file is memory mapped.

Parameters
toutThe maximum number of seconds to wait for the shared memory file to become available. If tout is zero, then the file must be immediately available. If the value is negative then the attach waits as long as needed. When tout is reached the attach fails with errno set to ETIMEDOUT.
isrwWhen true the file is mapped to writable memory and allows updates to the table. If false, the shared memory is made read/only and may be significantly faster to access.
Returns
true - The shared memory was attached, the table can be used.
false - The shared memory could not be attached, errno holds reason.

Implements XrdSsiShMat.

Definition at line 350 of file XrdSsiShMam.cc.

351 {
352  FileHelper fileHelp(this);
353  XLockHelper lockInfo(this, (isrw ? RWLock : ROLock));
354  struct stat Stat1, Stat2;
355  int mMode, oMode;
356  union {int *intP; Atomic(int) *antP;} xntP;
357 
358 // Compute open and mmap options
359 //
360  if (isrw)
361  {oMode = O_RDWR;
362  mMode = PROT_READ|PROT_WRITE;
363  isRW = true;
364  } else {
365  oMode = O_RDONLY;
366  mMode = PROT_READ;
367  isRW = false;
368  }
369 
370 // Attempt to open the file
371 //
372  timeOut = tout;
373  if (tout < 0) tout = 0x7fffffff;
374  while((shmFD = ShMam_Open(shmPath, oMode)) < 0 && tout >= 0)
375  {if (errno != ENOENT) return false;
376  if (!tout) break;
377  Snooze(3);
378  tout -= 3;
379  }
380 
381 // Test if we timed out
382 //
383  if (tout <= 0) {errno = ETIMEDOUT; return false;}
384  fileHelp.autoClose = true;
385 
386 // Lock this file as we don't want it changing on us for now
387 //
388  if (!lockInfo.FLock()) return false;
389 
390 // Get the stat information for this file
391 //
392  if (fstat(shmFD, &Stat1)) return false;
393 
394 // The file is open, try to memory map it
395 //
396  shmBase = (char *)mmap(0, Stat1.st_size, mMode, MAP_SHARED, shmFD, 0);
397  if (shmBase == MAP_FAILED) return false;
398  shmSize = Stat1.st_size;
399 
400 // Make sure we have a valid hash name
401 //
402  if (!shmHash) memcpy(&shmHash, "c32 ", sizeof(int));
403 
404 // Verify tha the objects in this mapping are compatible with this object
405 //
406  if (SHMINFO(typeSz) != shmTypeSz || strcmp(shmType, SHMINFO(typeID))
407  || strcmp(shmImpl, SHMINFO(myName)) || shmHash != SHMINFO(hashID))
408  {errno = EDOM; return false;}
409 
410 // Copy out the information we can use locally
411 //
412  verNum = SHMINFO(verNum);
413  keyPos = SHMINFO(keyPos);
414  maxKLen = SHMINFO(maxKeySz);
415  xntP.intP = SHMADDR(int, SHMINFO(index)); shmIndex = xntP.antP;
416  shmSlots = SHMINFO(slots);
417  shmItemSz = SHMINFO(itemSz);
418  shmInfoSz = SHMINFO(infoSz);
419 
420 // Now, there is a loophole here as the file could have been exported while
421 // we were trying to attach it. If this happened, the inode would change.
422 // We test for this now. If it changed, tell the caller to try again.
423 //
424  if (stat(shmPath, &Stat2)
425  || Stat1.st_dev != Stat2.st_dev || Stat1.st_ino != Stat2.st_ino)
426  {errno = EAGAIN; return false;}
427  accMode = Stat2.st_mode & (S_IRWXU|S_IRWXG|S_IRWXO);
428 
429 // Set locking based on how the table was created
430 //
431  SetLocking(isrw);
432  fileHelp.autoClose = false;
433  return true;
434 }
int stat(const char *path, struct stat *buf)
int fstat(int fildes, struct stat *buf)
#define Atomic(type)
#define SHMADDR(type, offs)
Definition: XrdSsiShMam.cc:88
char * shmPath
Definition: XrdSsiShMat.hh:361
char * shmType
Definition: XrdSsiShMat.hh:362
char * shmImpl
Definition: XrdSsiShMat.hh:360

References Atomic, fstat(), ROLock, RWLock, SHMADDR, XrdSsiShMat::shmHash, XrdSsiShMat::shmImpl, SHMINFO, XrdSsiShMat::shmPath, XrdSsiShMat::shmType, XrdSsiShMat::shmTypeSz, and stat().

+ Here is the call graph for this function:

◆ Create()

bool XrdSsiShMam::Create ( XrdSsiShMat::CRZParms parms)
virtual

Implements XrdSsiShMat.

Definition at line 440 of file XrdSsiShMam.cc.

441 {
442  static const int minInfoSz = 256;
443  static const int okMode = S_IRWXU|S_IRWXG|S_IROTH;
444  static const int crMode = S_IRWXU|S_IRWXG|S_IROTH;
445  FileHelper fileHelp(this);
446  ShmInfo theInfo;
447  int n, maxEnts, totSz, indexSz;
448  union {int *intP; Atomic(int) *antP;} xntP;
449 
450 // Validate parameter list values
451 //
452  if (parms.indexSz <= 0 || parms.maxKeys <= 0 || parms.maxKLen <= 0)
453  {errno = EINVAL; return false;}
454  if (parms.mode & ~okMode || ((parms.mode & crMode) != crMode))
455  {errno = EACCES; return false;}
456 
457 // We need the reuse and multw options later so calclulate them now
458 //
459  reUse = (parms.reUse <= 0 ? false : true);
460  multW = (parms.multW <= 0 ? false : true);
461 
462 // Clear the memory segment information we will be constructing
463 //
464  memset(&theInfo, 0, sizeof(theInfo));
465 
466 // Calculate the info header size (we round up to 1K)
467 //
468  shmInfoSz = (sizeof(ShmInfo)+minInfoSz-1)/minInfoSz*minInfoSz;
469  theInfo.lowFree = theInfo.infoSz = shmInfoSz;
470 
471 // Calculate the size of each item (rounded to a doubleword)
472 //
473  shmItemSz = (shmTypeSz + parms.maxKLen+1 + sizeof(MemItem) + 7)/8*8;
474  theInfo.itemSz = shmItemSz;
475 
476 // Calculate total amount we need for the items
477 //
478  maxEnts = parms.maxKeys;
479  totSz = shmItemSz * maxEnts;
480  totSz = (totSz+7)/8*8;
481 
482 // Calculate the amount we need for the index
483 //
484  indexSz = parms.indexSz*sizeof(int);
485  indexSz = (indexSz+7)/8*8;
486 
487 // Compute total size and adjust it to be a multiple of the page size
488 //
489  totSz = totSz + indexSz + shmInfoSz;
490  totSz = (totSz/PageSize+1)*PageSize;
491 
492 // Generate the hashID if not specified
493 //
494  if (!shmHash) memcpy(&shmHash, "c32 ", sizeof(int));
495 
496 // Complete the shared memory segment information structure
497 //
498  theInfo.index = totSz-indexSz;
499  theInfo.slots = parms.indexSz;
500  theInfo.typeSz = shmTypeSz;
501  theInfo.highUse = theInfo.index;
502  theInfo.reUse = reUse;
503  theInfo.multW = multW;
504  theInfo.keyPos = keyPos = shmTypeSz + sizeof(MemItem);
505  theInfo.maxKeys = maxEnts;
506  theInfo.maxKeySz = maxKLen = parms.maxKLen;
507  theInfo.hashID = shmHash;
508  strncpy(theInfo.typeID, shmType, sizeof(theInfo.typeID)-1);
509  strncpy(theInfo.myName, shmImpl, sizeof(theInfo.myName)-1);
510 
511 // Create the new filename of the new file we will create
512 //
513  n = strlen(shmPath);
514  shmTemp = (char *)malloc(n+8);
515  sprintf(shmTemp, "%s.new", shmPath);
516 
517 // Open the file creaing as necessary
518 //
519  if ((shmFD = ShMam_Open(shmTemp, O_RDWR|O_CREAT, parms.mode)) < 0)
520  return false;
521  accMode = parms.mode;
522  fileHelp.autoClose = true;
523 
524 // Verify that no one else is using this file.
525 //
526  if (!Lock(true, true)) {errno = EADDRINUSE; return false;}
527 
528 // Make the file as large as need be
529 //
530  if (ftruncate(shmFD, 0) || ftruncate(shmFD, totSz)) return false;
531 
532 // Map the file as a writable shared segment
533 //
534  shmBase = (char *)mmap(0, totSz, PROT_READ|PROT_WRITE, MAP_SHARED, shmFD, 0);
535  if (shmBase == MAP_FAILED) return false;
536  shmSize = totSz;
537  isRW = true;
538 
539 // Copy the segment information into the segment
540 //
541  memcpy(shmBase, &theInfo, sizeof(theInfo));
542  xntP.intP = SHMADDR(int, SHMINFO(index)); shmIndex = xntP.antP;
543  shmSlots = parms.indexSz;
544 
545 // A created table has, by definition, a single writer until it is exported.
546 // So, we simply keep the r/w lock on the file until we export the file. Other
547 // threads won't change that and other process will not be able to use the file.
548 //
549  lockRO = lockRW = false;
550  fileHelp.autoClose = false;
551  return true;
552 }
int ftruncate(int fildes, off_t offset)
static const int PageSize
int maxKeys
Maximum number of keys-value pairs expected in table.
Definition: XrdSsiShMat.hh:101
int maxKLen
The maximum acceptable key length.
Definition: XrdSsiShMat.hh:102
int mode
Filemode for the newly created file.
Definition: XrdSsiShMat.hh:103
int indexSz
Number of four byte hash table entries to create.
Definition: XrdSsiShMat.hh:100

References ftruncate(), XrdSsiShMat::CRZParms::indexSz, XrdSsiShMat::CRZParms::maxKeys, XrdSsiShMat::CRZParms::maxKLen, XrdSsiShMat::CRZParms::mode, XrdSsiShMat::CRZParms::multW, XrdSys::PageSize, XrdSsiShMat::CRZParms::reUse, SHMADDR, XrdSsiShMat::shmHash, XrdSsiShMat::shmImpl, SHMINFO, XrdSsiShMat::shmPath, XrdSsiShMat::shmType, and XrdSsiShMat::shmTypeSz.

Referenced by Resize().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ DelItem()

bool XrdSsiShMam::DelItem ( void *  data,
const char *  key,
int  hash 
)
virtual

Delete an item from the table.

Parameters
dataPointer to the area to receive the value of the deleted key. If the pointer is nil, then the key value is not returned.
keyPointer to the key of length <= MaxKLen.
hashThe hash of the key that is to be used to lookup the key. If the value is zero, an internal hash is computed.
Returns
true - The key and data have been deleted. This is always returned when data is nil.
false - The key and data either not deleted or the key does not exist and data was not nil. The errno value decribes why. Typical reason: the key was not found (errno == ENOENT).

Implements XrdSsiShMat.

Definition at line 558 of file XrdSsiShMam.cc.

559 {
560  XLockHelper lockInfo(this, RWLock);
561  MemItem *theItem, *prvItem;
562  int hEnt, iOff;
563 
564 // Make sure we can delete an item
565 //
566  if (!shmSize) {errno = ENOTCONN; return false;}
567  if (!isRW) {errno = EROFS; return false;}
568 
569 // Check if we need to remap this memory (atomic tests is not needed here)
570 //
571  if (verNum != SHMINFO(verNum)) ReMap(RWLock);
572 
573 // Lock the file if we have multiple writers or recycling items
574 // We need to do this prior to file locking as the requirements may change.
575 //
576  if (lockRW && !lockInfo.FLock()) return false;
577 
578 // First try to find the item
579 //
580  if (!(hEnt = Find(theItem, prvItem, key, hash)))
581  {if (data) {errno = ENOENT; return false;}
582  return true;
583  }
584 
585 // Return the contents of the item if the caller wishes that
586 //
587  if (data) memcpy(data, ITEM_VAL(theItem), shmTypeSz);
588 
589 // Delete the item from the index. The update of the count need not be atomic.
590 // Also fetching of the next offset need not be atomic as we are the only one.
591 //
592  iOff = theItem->next;
593  SHMINFO(itemCount)--;
594  if (prvItem) Atomic_SET_STRICT(prvItem->next, iOff); // Atomic
595  else {if (!iOff) SHMINFO(slotsUsed)--;
596  Atomic_SET_STRICT(shmIndex[hEnt],iOff); // Atomic
597  }
598  RetItem(theItem);
599 
600 // Indicate the things we updated if need be
601 //
602  if (syncOn)
603  {Updated(0);
604  Updated(SHMOFFS(theItem));
605  if (prvItem) Updated(SHMOFFS(prvItem));
606  else Updated(SHMOFFS(&shmIndex[hEnt]));
607  }
608 
609 // All done
610 //
611  return true;
612 }

References ITEM_VAL, RWLock, SHMINFO, SHMOFFS, and XrdSsiShMat::shmTypeSz.

◆ Detach()

void XrdSsiShMam::Detach ( )
virtual

Detach the map from the shared memory.

Implements XrdSsiShMat.

Definition at line 618 of file XrdSsiShMam.cc.

619 {
620 // Clean up
621 //
622  if (shmFD >= 0) {close(shmFD); shmFD = -1;}
623  if (shmSize) {munmap(shmBase, shmSize); shmSize = 0;}
624  if (shmTemp) {free(shmTemp); shmTemp = 0;}
625  shmIndex = 0;
626 }
#define close(a)
Definition: XrdPosix.hh:43

References close.

Referenced by ~XrdSsiShMam().

+ Here is the caller graph for this function:

◆ Enumerate() [1/2]

bool XrdSsiShMam::Enumerate ( void *&  jar)
virtual

Terminate an active enumeration. An active enumeration is any enumeration where the previous form of Enumerate() did not return false. Terminating an active enumeration releases all of the enumeration resources allocated.

Parameters
jarThe opaque cookie initialized by a previous call to Enumerate() requesting the next key-value pair.
Returns
true The enumeration has been terminated and the jar was deleted and the jar pointer is set to zero. Keys are returned in arbitrary order and not all keys may be returned if the map is being actively updated.
false The jar pointer was zero; no enumeration was active.

Implements XrdSsiShMat.

Definition at line 632 of file XrdSsiShMam.cc.

633 {
634  EnumJar *theJar = (EnumJar *)jar;
635 
636 // Close off the enumeration
637 //
638  if (theJar) {delete theJar; jar = 0;}
639  return true;
640 }

◆ Enumerate() [2/2]

bool XrdSsiShMam::Enumerate ( void *&  jar,
char *&  key,
void *&  val 
)
virtual

Enumerate the keys and assocaited values.

Parameters
jarAn opaque cookie that tracks progress. It should be initialized to zero and otherwise not touched. The same jar must be used for all successive calls. The jar is deleted when false is returned (also see the next Enumerate method).
keyThe pointer variable where the location of the key is returned upon success.
valThe pointer variable where the location f the key values is to be returned upon success.
Returns
true A key and val pointers have been set. Keys are returned in arbitrary order and not all keys may be returned if the map is being actively updated.
false Key not returned; errno holds the reason. Typically, ENOENT there ae no more keys. Other errors may also be reflected. Whne false is returned the jar is deleted and the pointer to it set to zero.

Implements XrdSsiShMat.

Definition at line 644 of file XrdSsiShMam.cc.

645 {
646  XLockHelper lockInfo(this, ROLock);
647  EnumJar *theJar = (EnumJar *)jar;
648  MemItem *theItem;
649  long long iTest;
650  int rc, newFD, fence, iOff, hash = 0;
651 
652 // Make sure we can get an item
653 //
654  if (!shmSize) {errno = ENOTCONN; return false;}
655 
656 // If this is the first call, initialize the jar. First check if we need to
657 // remap the segment. We need to do this prior to file locking as the
658 // requirements may change. Then create a jar and a shadow copy of the segment.
659 //
660  if (!jar)
661  {if (verNum != SHMINFO(verNum)) ReMap(ROLock);
662  if ((newFD = ShMam_Dup(shmFD)) < 0) return false;
663  theJar = new EnumJar(newFD, shmItemSz);
664  jar = theJar;
665  } else if (theJar->iNum < 0)
666  {Enumerate(jar);
667  errno = ENOENT;
668  return false;
669  }
670 
671 // Lock the file if we have multiple writers or recycling items
672 //
673  if (lockRO && !lockInfo.FLock())
674  {rc = errno; Enumerate(jar); errno = rc; return false;}
675 
676 // Compute the next key we should start the search at but make sure it will not
677 // generate an overflow. In the process we fetch the stopping point only once.
678 //
679  iTest = (static_cast<long long>(theJar->iNum) * shmItemSz) + shmInfoSz;
680  fence = SHMINFO(lowFree); // Atomic??
681  if (iTest < fence) iOff = static_cast<int>(iTest);
682  else iOff = fence;
683 
684 // Now start the search. Note that pread() must do a memory fence.
685 //
686  theItem = (MemItem *)(theJar->buff);
687  while(iOff < fence)
688  {rc = pread(theJar->fd, theJar->buff, shmItemSz, iOff);
689  if (rc < 0) return false;
690  if (rc != shmItemSz) break;
691  if ((hash = theItem->hash)) break; // Atomic
692  iOff += shmItemSz;
693  }
694 
695 // Check if we found a key
696 //
697  if (!hash) {Enumerate(jar); errno = ENOENT; return false;}
698 
699 // Return the key and and the associated value
700 //
701  key = ITEM_KEY(theItem);
702  val = ITEM_VAL(theItem);
703 
704 // Compute the contents of the new jar
705 //
706  theJar->iNum = (iOff - shmInfoSz)/shmItemSz + 1;
707  return true;
708 }
ssize_t pread(int fildes, void *buf, size_t nbyte, off_t offset)
bool Enumerate(void *&jar, char *&key, void *&val)
Definition: XrdSsiShMam.cc:644

References ITEM_KEY, ITEM_VAL, pread(), ROLock, and SHMINFO.

+ Here is the call graph for this function:

◆ Export()

bool XrdSsiShMam::Export ( )
virtual

Export a newly created table (i.e. see Create()).

Returns
true - The table has been exported and is now visible to others.
false - The export failed, the errno value describes the reason.

Implements XrdSsiShMat.

Definition at line 714 of file XrdSsiShMam.cc.

715 {
716  MutexHelper mtHelp(&myMutex, RWLock);
717 
718 // Make sure we are attached and in R/W mode and exportable
719 //
720  if (!shmSize) {errno = ENOTCONN; return false;}
721  if (!shmTemp) {errno = ENOPROTOOPT; return false;}
722  if (!isRW) {errno = EROFS; return false;}
723 
724 // All that is left is to export the file using the internal interface. Tell
725 // the exporter that we don't have the original file locked.
726 //
727  return ExportIt(false);
728 }

References RWLock.

◆ GetItem()

bool XrdSsiShMam::GetItem ( void *  data,
const char *  key,
int  hash 
)
virtual

Get an item from the table.

Parameters
dataPointer to an area to receive the value associated with key. If the pointer is nil, then the key value is not returned.
keyPointer to the key of length <= MaxKLen.
hashThe hash of the key that is to be used to lookup the key. If the value is zero, an internal hash is computed.
Returns
true - The key was found and if data was not nil, contains the value associated key.
false - The key not found; errno holds the reason (typically is ENOENT but may be some other reason).

Implements XrdSsiShMat.

Definition at line 854 of file XrdSsiShMam.cc.

855 {
856  XLockHelper lockInfo(this, ROLock);
857  MemItem *theItem, *prvItem;
858  int hEnt;
859 
860 // Make sure we can get an item
861 //
862  if (!shmSize) {errno = ENOTCONN; return false;}
863 
864 // Check if we need to remap this memory (atomic tests is not needed here)
865 // We need to do this prior to file locking as the requirements may change.
866 //
867  if (verNum != SHMINFO(verNum)) ReMap(ROLock);
868 
869 // Lock the file if we have multiple writers or recycling items
870 //
871  if (lockRO && !lockInfo.FLock()) return false;
872 
873 // First try to find the item
874 //
875  if (!(hEnt = Find(theItem, prvItem, key, hash)))
876  {errno = ENOENT; return false;}
877 
878 // Return the contents of the item if the caller wishes that
879 //
880  if (data) memcpy(data, ITEM_VAL(theItem), shmTypeSz);
881 
882 // All done
883 //
884  return true;
885 }

References ITEM_VAL, ROLock, SHMINFO, and XrdSsiShMat::shmTypeSz.

◆ Info()

int XrdSsiShMam::Info ( const char *  vname,
char *  buff = 0,
int  blen = 0 
)
virtual

Return information about the table.

Parameters
vnamePointer to the variable name whose value is wanted. A particular implementation may not support all variable and may support variables not listed here. These are for the default implementation unless otherwise noted. They are: hash - name of hash being used. impl - The table implementation being used. indexsz - Number of index entries indexused - Number of index entries in use keys - Number of keys in the bale. keys/indexused is the hash table collision factor keysfree - Number of keys that can still be added maxkeylen - Longest allowed key multw - If table supports multiple writers, else 0 reuse - If table allows object reuse, else 0 type - Name of the data type in the table. typesz - The number of bytes in the table's data type
buff- Pointer to the buffer to receive text values. Variables that return text are: hash, impl, and type. A buffer must be supplied in any of these variables are requested. If buff is nill or too small a -1 is returned with errno set to EMSGSIZE.
blenThe length of the buffer.
Returns
>=0 - The variable's value or the length of the text information.
< 0 - The variable's value could not be returned; errno has the error code describing the reason, typically ENOTSUP.

Implements XrdSsiShMat.

Definition at line 961 of file XrdSsiShMam.cc.

962 {
963  MutexHelper mtHelp(&myMutex, ROLock);
964 
965 // Make sure we can delete an item
966 //
967  if (!shmSize) {errno = ENOTCONN; return 0;}
968 
969  if (!strcmp(vname, "atomics"))
970  {int n = strlen(Atomic_IMP);
971  strcpy(buff, Atomic_IMP);
972  return n;
973  }
974 
975  if (!strcmp(vname, "hash"))
976  {if (!buff || blen < (int)(sizeof(int)+1)) {errno = EMSGSIZE; return -1;}
977  memcpy(buff, &SHMINFO(hashID), sizeof(int)); buff[sizeof(int)] = 0;
978  return strlen(buff);
979  }
980  if (!strcmp(vname, "impl"))
981  {int n = strlen(SHMINFO(myName));
982  if (!buff || blen < n) {errno = EMSGSIZE; return -1;}
983  strcpy(buff, SHMINFO(myName));
984  return n;
985  }
986  if (!strcmp(vname, "flockro")) return lockRO;
987  if (!strcmp(vname, "flockrw")) return lockRW;
988  if (!strcmp(vname, "indexsz")) return shmSlots;
989  if (!strcmp(vname, "indexused")) return SHMINFO(slotsUsed);
990  if (!strcmp(vname, "keys")) return SHMINFO(itemCount); // Atomic
991  if (!strcmp(vname, "keysfree"))
992  return (SHMINFO(highUse) - SHMINFO(lowFree))/shmItemSz
993  + SHMINFO(freeCount);
994  if (!strcmp(vname, "maxkeylen")) return SHMINFO(maxKeySz);
995  if (!strcmp(vname, "multw")) return multW;
996  if (!strcmp(vname, "reuse")) return reUse;
997  if (!strcmp(vname, "type"))
998  {int n = strlen(SHMINFO(typeID));
999  if (!buff || blen < n) {errno = EMSGSIZE; return -1;}
1000  strcpy(buff, SHMINFO(typeID));
1001  return n;
1002  }
1003  if (!strcmp(vname, "typesz")) return SHMINFO(typeSz);
1004 
1005 // Return variable not supported
1006 //
1007  errno = ENOTSUP;
1008  return -1;
1009 }
#define Atomic_IMP

References Atomic_IMP, ROLock, and SHMINFO.

◆ Resize()

bool XrdSsiShMam::Resize ( XrdSsiShMat::CRZParms parms)
virtual

Resize a shared memory segment and associated file specified at object instantiation (see New() method). Resizing is implementation specific but may involve creating a new table and exporting it.

Parameters
parmsResize parameters. See the CRZParms struct for details. For resize, zero values or unspecified flags use the existing table values.
Returns
true - The shared memory was resized, the table can be used.
false - The shared memory could not be resized, errno holds reason.

Implements XrdSsiShMat.

Definition at line 1087 of file XrdSsiShMam.cc.

1088 {
1089  XLockHelper lockInfo(this, RWLock);
1090  XrdSsiShMat::NewParms newParms;
1091  MemItem *theItem;
1092  void *val;
1093  char *key;
1094  int fence, iOff, hash;
1095 
1096 // Make sure we can delete an item
1097 //
1098  if (!shmSize) {errno = ENOTCONN; return false;}
1099  if (!isRW) {errno = EROFS; return false;}
1100 
1101 // Validate parameter list values
1102 //
1103  if (parms.indexSz < 0 || parms.maxKeys < 0 || parms.maxKLen < 0)
1104  {errno = EINVAL; return false;}
1105 
1106 // A resize is not permitted on an un-exported segment
1107 //
1108  if (shmTemp) {errno = EPERM; return false;}
1109 
1110 // Check if we need to remap this memory (atomic tests is not needed here)
1111 //
1112  if (verNum != SHMINFO(verNum)) ReMap(RWLock);
1113 
1114 // Lock the source file
1115 //
1116  if (!lockInfo.FLock()) return false;
1117 
1118 // Setup parms for the segment object
1119 //
1120  newParms.impl = shmImpl;
1121  newParms.path = shmPath;
1122  newParms.typeID = shmType;
1123  newParms.typeSz = shmTypeSz;
1124  newParms.hashID = shmHash;
1125 
1126 // Create a new segment object (this cannot fail).
1127 //
1128  XrdSsiShMam newMap(newParms);
1129 
1130 // Set the values in the parameter list for those wanting the current setting.
1131 //
1132  if (!parms.indexSz) parms.indexSz = shmSlots;
1133  if (!parms.maxKeys) parms.maxKeys = SHMINFO(maxKeys);
1134  if (!parms.maxKLen) parms.maxKLen = maxKLen;
1135  if (parms.reUse < 0) parms.reUse = reUse;
1136  if (parms.multW < 0) parms.multW = multW;
1137 
1138 // Create the new target file
1139 //
1140  parms.mode = accMode;
1141  if (!newMap.Create(parms)) return false;
1142 
1143 // Compute the offset of the first item and get the offset of the last item.
1144 //
1145  fence = SHMINFO(lowFree); // Atomic??
1146  iOff = shmInfoSz;
1147 
1148 // For each item found in the current map add it to the new map
1149 //
1150  while(iOff < fence)
1151  {theItem = SHMADDR(MemItem, iOff);
1152  if ((hash = theItem->hash))
1153  {key = ITEM_KEY(theItem);
1154  val = ITEM_VAL(theItem);
1155  if (!newMap.AddItem(val, 0, key, hash, true)) return false;
1156  }
1157  iOff += shmItemSz;
1158  }
1159 
1160 // We need to drop the lock on the file otherwise the export will hang
1161 //
1162 
1163 // All went well, so export this the new map using the internal interface as
1164 // we already have the source file locked and export normally tries to lock it.
1165 //
1166  if (!newMap.ExportIt(true)) return false;
1167 
1168 // All that we need to do is to swap the map with our map and we are done.
1169 //
1170  SwapMap(newMap);
1171  return true;
1172 }
const char * typeID
The name of the type associated with the key.
Definition: XrdSsiShMat.hh:279
const char * impl
Implementation name.
Definition: XrdSsiShMat.hh:277
const char * path
The path to the backing file for the table.
Definition: XrdSsiShMat.hh:278
int hashID
The hash being used (0 means the default)
Definition: XrdSsiShMat.hh:281
int typeSz
Size of the type in bytes.
Definition: XrdSsiShMat.hh:280

References AddItem(), Create(), XrdSsiShMat::NewParms::hashID, XrdSsiShMat::NewParms::impl, XrdSsiShMat::CRZParms::indexSz, ITEM_KEY, ITEM_VAL, XrdSsiShMat::CRZParms::maxKeys, XrdSsiShMat::CRZParms::maxKLen, XrdSsiShMat::CRZParms::mode, XrdSsiShMat::CRZParms::multW, XrdSsiShMat::NewParms::path, XrdSsiShMat::CRZParms::reUse, RWLock, SHMADDR, XrdSsiShMat::shmHash, XrdSsiShMat::shmImpl, SHMINFO, XrdSsiShMat::shmPath, XrdSsiShMat::shmType, XrdSsiShMat::shmTypeSz, XrdSsiShMat::NewParms::typeID, and XrdSsiShMat::NewParms::typeSz.

+ Here is the call graph for this function:

◆ Sync() [1/3]

bool XrdSsiShMam::Sync ( )
virtual

Synchronize all modified pages to the associated backing file.

Returns
true - Operation completed successfully.
false - Operation failed; errno holds the error code explaining why.

Implements XrdSsiShMat.

Definition at line 1274 of file XrdSsiShMam.cc.

1275 {
1276  MutexHelper mtHelp(&myMutex, RWLock);
1277 
1278 // Make sure we are attached and in R/W mode
1279 //
1280  if (!shmSize) {errno = ENOTCONN; return false;}
1281  if (!isRW) {errno = EROFS; return false;}
1282 
1283 // For now do a flush as this works in Linux. We may need to generalize this
1284 // for all platforms using msync, sigh.
1285 //
1286  if (!Flush()) return false;
1287 
1288 // Reset counters
1289 //
1290  syncBase = false;
1291  syncLast = 0;
1292  syncQWR = 0;
1293  return true;
1294 }

References RWLock.

◆ Sync() [2/3]

bool XrdSsiShMam::Sync ( bool  dosync,
bool  syncdo 
)
virtual

Turn memry synchronization on or off.

Parameters
dosyncWhen true, modified table pages are written back to the backing file. The synchronous or async nature of the write is controlled by the second parameter. When false, memory-file synchronization is turned off (initial setting).
syncdoWhen true, synchronization is done in the forground. That is, a call triggering a sync will not return until complete. When false, synchronization is done in the background.
Returns
true - Operation completed successfully.
false - Operation failed; errno holds the error code explaining why.

Implements XrdSsiShMat.

Definition at line 1320 of file XrdSsiShMam.cc.

1321 {
1322  MutexHelper mtHelp(&myMutex, RWLock);
1323 
1324 // Make sure we are attached and in R/W mode
1325 //
1326  if (!shmSize) {errno = ENOTCONN; return false;}
1327  if (!isRW) {errno = EROFS; return false;}
1328 
1329 // Flush out pages if sync it turned on
1330 //
1331  if (syncOn && !Flush()) return false;
1332 
1333 // Set new options
1334 //
1335  syncOn = dosync;
1336  syncOpt = (syncdo ? MS_SYNC : MS_ASYNC);
1337  return true;
1338 }

References RWLock.

◆ Sync() [3/3]

bool XrdSsiShMam::Sync ( int  synqsz)
virtual

Set the sync defer queue size.

Parameters
synqszThe maximum number of modified pages before flushing.
Returns
true - Operation completed successfully.
false - Operation failed; errno holds the error code explaining why.

Implements XrdSsiShMat.

Definition at line 1298 of file XrdSsiShMam.cc.

1299 {
1300  MutexHelper mtHelp(&myMutex, RWLock);
1301 
1302 // Make sure we are attached and in R/W mode
1303 //
1304  if (!shmSize) {errno = ENOTCONN; return false;}
1305  if (!isRW) {errno = EROFS; return false;}
1306  if (syncqsz < 0) {errno = EINVAL; return false;}
1307 
1308 // Flush out pages if sync it turned on
1309 //
1310  if (syncOn && !Flush()) return false;
1311 
1312 // Set new queue size
1313 //
1314  syncQSZ = syncqsz;
1315  return true;
1316 }

References RWLock.


The documentation for this class was generated from the following files: